Python HTTPS代理隧道

the*_*ree 5 python proxy http connect tunnel

我正在尝试在python中创建一个http代理.到目前为止,除了https工作之外,我已经得到了所有东西,因此下一步是实现CONNECT方法.

我对进行https隧道传输时需要发生的事件链稍微感到困惑.从我的理解,我应该有这个连接到谷歌:

Broswer - >代理

CONNECT www.google.co.uk:443 HTTP/1.1\r\n\r\n
Run Code Online (Sandbox Code Playgroud)

然后代理应建立与google.co.uk的安全连接,并通过发送确认:

代理 - >浏览器

HTTP/1.1 200 Connection established\r\n\r\n
Run Code Online (Sandbox Code Playgroud)

在这一点上,我希望浏览器现在可以继续执行它首先要做的事情,但是,我要么什么也得不到,或者得到一串我无法解码的字节().我一直在阅读任何与ssl隧道有关的事情,我想我应该将所有字节从浏览器转发到服务器,以及相反的方式.但是,当这样做时,我得到一个:

HTTP/1.0 400 Bad Request\r\n...\r\n
Run Code Online (Sandbox Code Playgroud)

一旦我发送了200个代码,接下来我应该做什么?

我的connect方法的代码片段:

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

if headers["Method"] == "CONNECT":
    client = ssl.wrap_socket(client)

    try:
        client.connect(( headers["Host"], headers["Port"] ))
        reply = "HTTP/1.0 200 Connection established\r\n"
        reply += "Proxy-agent: Pyx\r\n"
        reply += "\r\n"
        browser.sendall( reply.encode() )
    except socket.error as err:
        print(err)
        break

    while True:
        now not sure
Run Code Online (Sandbox Code Playgroud)

非常感谢帮助!

the*_*ree 5

在找到相关问题的答案后:HTTPS Proxy Implementation (SSLStream)

我意识到目标服务器(在本例中为 google.co.uk)的端口 443 上的初始连接不应该被加密。因此我删除了

client = ssl.wrap_socket(client)
Run Code Online (Sandbox Code Playgroud)

行继续使用纯文本隧道而不是 ssl。一旦

HTTP/1.1 200 Connection established\r\n\r\n
Run Code Online (Sandbox Code Playgroud)

发送消息后,浏览器和端服务器将通过代理形成自己的 ssl 连接,因此代理不需要做任何与实际 https 连接相关的事情。

修改后的代码(包括字节转发):

# If we receive a CONNECT request
if headers["Method"] == "CONNECT":
    # Connect to port 443
    try:
        # If successful, send 200 code response
        client.connect(( headers["Host"], headers["Port"] ))
        reply = "HTTP/1.0 200 Connection established\r\n"
        reply += "Proxy-agent: Pyx\r\n"
        reply += "\r\n"
        browser.sendall( reply.encode() )
    except socket.error as err:
        # If the connection could not be established, exit
        # Should properly handle the exit with http error code here
        print(err)
        break

    # Indiscriminately forward bytes
    browser.setblocking(0)
    client.setblocking(0)
    while True:
        try:
            request = browser.recv(1024)
            client.sendall( request )
        except socket.error as err:
            pass
        try:
            reply = client.recv(1024)
            browser.sendall( reply )
        except socket.error as err:
            pass
Run Code Online (Sandbox Code Playgroud)

参考:

HTTPS 代理实现 (SSLStream)

http://tools.ietf.org/html/draft-luotonen-ssl-tunneling-03

http://www.ietf.org/rfc/rfc2817.txt