首页 > 解决方案 > 处理 CONNECT 请求的 Python 代理服务器

问题描述

我正在尝试构建一个可以同时处理 HTTP 和 HTTPS 请求的代理,它适用于 GET 和 POST 等 HTTP 请求,但对于 CONNECT 请求,我没有从 Web 服务器得到响应。

这是我的代理的一个更简单的版本,它说明了这个问题。

import socket

IP = "0.0.0.0"
PORT = 1234

server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
server_socket.bind((IP, PORT))
server_socket.listen()

while True: 
    conn, _ = server_socket.accept()

    header_bytes, _ = conn.recv(1024).split(b"\r\n\r\n")
    header_bytes += b"\r\n\r\n"

    print("header: ", header_bytes)

    for header in header_bytes.split(b"\r\n"):
        key, value = header.split(b":", 1)
        if key == b"Host":
            if b":" not in value:
                value += b":80"
            break

    addr, port = value.split(b":")

    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    client_socket.connect((addr.decode("utf-8").replace(" ", ""), int(port.decode("utf-8"))))

    client_socket.send(header_bytes)
    response = client_socket.recv(1024)

    print("response: ", response)
    conn.send(response)
    conn.close()

我得到的是

header:  b'CONNECT www.google.com:443 HTTP/1.1\r\n
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:75.0) Gecko/20100101 Firefox/75.0\r\n
Proxy-Connection: keep-alive\r\n
Connection: keep-alive\r\n
Host: www.google.com:443\r\n\r\n'
response:  b'' 

在阅读了有关 CONNECT请求的更多信息后,我想我可能误解了它应该如何工作,但我仍然不明白我该如何实现它。它说我必须建立到 Web 服务器的隧道,但是如果我的 CONNECT 请求没有得到响应,我该怎么做。我是否只是发送 200 OK 响应并假装我有隧道?

标签: pythonsocketshttps

解决方案


一个普通的 HTTP 请求(GET、POST、...)被代理转发到服务器(通常在重写路径以不再是完整的 URL 之后),并且来自服务器的响应被发送回客户端。但使用 CONNECT 时,情况有所不同。

CONNECT 请求仅从客户端发送到代理。它不会转发到服务器。相反,代理将建立与服务器的 TCP 连接,并在此成功后向客户端返回成功响应,即HTTP/1.0 200 .... 换句话说:CONNECT 请求/响应仅在客户端和代理之间,服务器对此一无所知。

一旦与服务器的 TCP 连接建立并且 HTTP 响应发送到客户端,客户端的所有数据都应该转发到服务器,服务器的所有数据都应该转发到客户端。


推荐阅读