一个欲儿的博客

一个欲儿的博客

流量转发HTTP、HTTPS
2025-04-22

流量转发HTTP、HTTPS

import socket
import threading
import select

LISTEN_HOST = '0.0.0.0'
LISTEN_PORT = 8080  # 建议避开 80,用 8080、8888 更通用

def handle(client_socket):
    try:
        request_line = client_socket.recv(4096).split(b'\n')[0]
        if not request_line:
            client_socket.close()
            return

        method, url, _ = request_line.decode(errors='ignore').split()
        if method == 'CONNECT':
            target_host, target_port = url.split(':')
            target_port = int(target_port)
            remote = socket.create_connection((target_host, target_port))
            client_socket.sendall(b"HTTP/1.1 200 Connection Established\r\n\r\n")
        else:
            from urllib.parse import urlparse
            parsed = urlparse(url)
            target_host = parsed.hostname
            target_port = parsed.port or 80
            remote = socket.create_connection((target_host, target_port))
            remote.sendall(request_line + b'\r\n')

        exchange(client_socket, remote)
    except:
        client_socket.close()

def exchange(sock1, sock2):
    sockets = [sock1, sock2]
    try:
        while True:
            r, _, _ = select.select(sockets, [], [])
            for s in r:
                data = s.recv(8192)
                if not data:
                    return
                if s == sock1:
                    sock2.sendall(data)
                else:
                    sock1.sendall(data)
    finally:
        sock1.close()
        sock2.close()

def start():
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.bind((LISTEN_HOST, LISTEN_PORT))
    s.listen(128)
    print(f"HTTP Proxy Running on {LISTEN_HOST}:{LISTEN_PORT}")
    while True:
        client, _ = s.accept()
        threading.Thread(target=handle, args=(client,), daemon=True).start()

if __name__ == '__main__':
    start()


发表评论: