66 lines
2.2 KiB
Python
66 lines
2.2 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""
|
|
proxy.py
|
|
~~~~~~~~
|
|
⚡⚡⚡ Fast, Lightweight, Pluggable, TLS interception capable proxy server focused on
|
|
Network monitoring, controls & Application development, testing, debugging.
|
|
|
|
:copyright: (c) 2013-present by Abhinav Singh and contributors.
|
|
:license: BSD, see LICENSE for more details.
|
|
"""
|
|
from typing import Optional, Tuple, Callable
|
|
|
|
import paramiko
|
|
|
|
|
|
class Tunnel:
|
|
"""Establishes a tunnel between local (machine where Tunnel is running) and remote host.
|
|
Once a tunnel has been established, remote host can route HTTP(s) traffic to
|
|
localhost over tunnel.
|
|
"""
|
|
|
|
def __init__(
|
|
self,
|
|
ssh_username: str,
|
|
remote_addr: Tuple[str, int],
|
|
private_pem_key: str,
|
|
remote_proxy_port: int,
|
|
conn_handler: Callable[[paramiko.channel.Channel], None]) -> None:
|
|
self.remote_addr = remote_addr
|
|
self.ssh_username = ssh_username
|
|
self.private_pem_key = private_pem_key
|
|
self.remote_proxy_port = remote_proxy_port
|
|
self.conn_handler = conn_handler
|
|
|
|
def run(self) -> None:
|
|
ssh = paramiko.SSHClient()
|
|
ssh.load_system_host_keys()
|
|
ssh.set_missing_host_key_policy(paramiko.WarningPolicy())
|
|
try:
|
|
ssh.connect(
|
|
hostname=self.remote_addr[0],
|
|
port=self.remote_addr[1],
|
|
username=self.ssh_username,
|
|
key_filename=self.private_pem_key
|
|
)
|
|
print('SSH connection established...')
|
|
transport: Optional[paramiko.transport.Transport] = ssh.get_transport(
|
|
)
|
|
assert transport is not None
|
|
transport.request_port_forward('', self.remote_proxy_port)
|
|
print('Tunnel port forward setup successful...')
|
|
while True:
|
|
conn: Optional[paramiko.channel.Channel] = transport.accept(
|
|
timeout=1)
|
|
assert conn is not None
|
|
e = transport.get_exception()
|
|
if e:
|
|
raise e
|
|
if conn is None:
|
|
continue
|
|
self.conn_handler(conn)
|
|
except KeyboardInterrupt:
|
|
pass
|
|
finally:
|
|
ssh.close()
|