Skip to content

Instantly share code, notes, and snippets.

@joshfinley
Created November 15, 2023 17:28
Show Gist options
  • Save joshfinley/7a8821147a160f2a48e83d8e2aa81056 to your computer and use it in GitHub Desktop.
Save joshfinley/7a8821147a160f2a48e83d8e2aa81056 to your computer and use it in GitHub Desktop.
import paramiko
import socket
import select
def http_connect_tunnel(proxy_host, proxy_port, target_host, target_port):
"""
Establish an HTTP CONNECT tunnel through a proxy.
"""
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((proxy_host, proxy_port))
connect_command = f"CONNECT {target_host}:{target_port} HTTP/1.1\r\n\r\n"
s.send(connect_command.encode())
# Wait for the end of the headers
response = ""
while "\r\n\r\n" not in response:
response += s.recv(1).decode()
if "200 Connection established" not in response:
raise Exception("Unable to establish a connection through the HTTP proxy.")
return s
def setup_ssh_tunnel_over_http(proxy_host, proxy_port, ssh_host, ssh_port, username, password, local_bind_address, local_bind_port):
"""
Set up an SSH connection over an HTTP CONNECT tunnel and forward a local port.
"""
# Establish HTTP CONNECT tunnel
tunnel_socket = http_connect_tunnel(proxy_host, proxy_port, ssh_host, ssh_port)
# Set up SSH client
ssh_client = paramiko.SSHClient()
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# Wrap the tunnel socket in a Paramiko transport and connect
transport = paramiko.Transport(tunnel_socket)
transport.start_client()
transport.auth_password(username, password)
# Set up port forwarding
channel = transport.open_channel('direct-tcpip', (ssh_host, ssh_port), (local_bind_address, local_bind_port))
# Keep the tunnel open
while True:
r, w, x = select.select([tunnel_socket], [], [])
if tunnel_socket in r:
data = channel.recv(1024)
if len(data) == 0:
break
print(data)
channel.close()
transport.close()
ssh_client.close()
# Example usage
proxy_host = 'your.proxy.host'
proxy_port = 8080
ssh_host = 'your.ssh.host'
ssh_port = 22
username = 'your_username'
password = 'your_password'
local_bind_address = 'localhost'
local_bind_port = 10022
setup_ssh_tunnel_over_http(proxy_host, proxy_port, ssh_host, ssh_port, username, password, local_bind_address, local_bind_port)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment