Created
November 15, 2023 17:28
-
-
Save joshfinley/7a8821147a160f2a48e83d8e2aa81056 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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