Python HTTPS代理隧道

8
我正在尝试用Python制作一个HTTP代理。到目前为止,除了HTTPS之外,我已经完成了所有的工作,因此下一步是实现CONNECT方法。
在进行HTTPS隧道时,我对需要发生的事件顺序有些困惑。 根据我的理解,当连接到谷歌时,应该是这样的:
浏览器 -> 代理
CONNECT www.google.co.uk:443 HTTP/1.1\r\n\r\n

然后代理应该建立与google.co.uk的安全连接,并通过发送以下内容进行确认:
代理 -> 浏览器
HTTP/1.1 200 Connection established\r\n\r\n

在这一点上,我期望浏览器现在会继续执行它最初要做的事情,然而,我要么什么都得不到,要么得到一串无法解码的字节。我一直在阅读与SSL隧道有关的任何和所有内容,我认为我应该将浏览器到服务器的所有字节以及反过来的字节都转发。然而,当我这样做时,我得到了一个:
HTTP/1.0 400 Bad Request\r\n...\r\n

一旦我发送了200状态码,接下来我应该做什么?
我的连接方法的代码片段:
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
1个回答

7
在找到一个相关问题的答案后:HTTPS代理实现(SSLStream),我意识到目标服务器(在这种情况下是google.co.uk)上端口443的初始连接不应该加密。因此,我移除了...
client = ssl.wrap_socket(client)

如果要使用纯文本通道而不是SSL,请使用该行。

HTTP/1.1 200 Connection established\r\n\r\n

当消息发送后,浏览器和终端服务器将通过代理建立自己的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

参考文献:

HTTPS代理实现(SSLStream)

https://datatracker.ietf.org/doc/html/draft-luotonen-ssl-tunneling-03

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接