在 python 中加密到我的 HTTP 代理的连接

Encrypting connection to my HTTP Proxy in python

基本上,我正在尝试使用 python 中的套接字设置加密代理。目前我可以通过从客户端向代理服务器发送 HTTP CONNECT 并接收 'CODE 200 OK' 来建立连接 回复。代理服务器充当从客户端到所需 domain/Ip 的隧道并且工作得很好。

问题是:如何加密整个连接?第一个 HTTP 连接未加密,可以轻松嗅探和查看。

服务器代码如下:

import socket, threading
MAX_BUFFER = 64 * 512
class ClientThread(threading.Thread):

    def __init__(self, clientAddress, clientsocket):
        threading.Thread.__init__(self)
        self.browser = clientsocket


    def run(self): 
        while True:
            request = self.browser.recv(MAX_BUFFER)
            # parse the first line
            client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            webserver, port = self.get_domain_port(request)
            if 'CONNECT' in request:
            # Connect to port 443
                print request
                try:
                    # If successful, send 200 code response
                    client.connect(( webserver, port ))
                    reply = "HTTP/1.0 200 Connection established\r\n"
                    reply += "Proxy-agent: FIMA\r\n"
                    reply += "\r\n"
                    self.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
                    break
                # Indiscriminately forward bytes
                self.browser.setblocking(0)
                client.setblocking(0)
                while True:
                    try:
                        request = self.browser.recv(MAX_BUFFER)
                        client.sendall( request )

                    except socket.error as err:
                        pass
                    try:
                        reply = client.recv(MAX_BUFFER)
                        self.browser.sendall( reply )
                    except socket.error as err:
                        pass



        print ("Client at ", self.ssl_browser , " disconnected...")


    def get_domain_port(self, request):
        first_line = request.split('\n')[0]

        # get url
        url = first_line.split(' ')[1]

        http_pos = url.find("://") # find pos of ://
        if (http_pos==-1):
            temp = url
        else:
            temp = url[(http_pos+3):] # get the rest of url

        port_pos = temp.find(":") # find the port pos (if any)

        # find end of web server
        webserver_pos = temp.find("/")
        if webserver_pos == -1:
            webserver_pos = len(temp)

        webserver = ""
        port = -1
        if (port_pos==-1 or webserver_pos < port_pos): 

            # default port 
            port = 80 
            webserver = temp[:webserver_pos] 

        else: # specific port 
            port = int((temp[(port_pos+1):])[:webserver_pos-port_pos-1])
            webserver = temp[:port_pos] 

        return webserver, port




def main():
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    sock.bind(('192.168.1.107', 80))
    sock.listen(5)

    while True:
        conn, addr = sock.accept()
        newthread = ClientThread(addr, conn)
        newthread.daemon = True
        newthread.start()

    sock.shutdown(socket.SHUT_RDWR)
    sock.close()
if __name__ == "__main__":
    main()

通常的方法是使用 HTTP 代理并使用普通的 CONNECT 方法创建隧道。然后,此隧道用于客户端和服务器之间的端到端加密 HTTPS。

虽然也可以加密客户端和代理之间的连接,但对于 HTTPS 隧道,这会在客户端和服务器之间的加密之上导致客户端和代理之间的加密。为此,您需要创建的不是普通套接字,而是带有证书等的 SSL 套接字 - 有关如何执行此操作的 lots of documentation and examples

请注意,此设置并未得到普遍支持。某些浏览器(如 Firefox)支持此功能,而其他浏览器则不支持。非浏览器客户端通常不支持这样的设置。