got stuck programming https proxy - what to do nex

2019-07-27 07:34发布

I'm currently making a proxy which sits between the browser and the web. Everything works except https. I'm having troubles understanding some passages of it and haven't found many resources on the web. And so I'm stuck.

The code I'm using is:

conn, addr = server.accept()
request = conn.recv(9999) #get a CONNECT request
conn.send(b'HTTP/1.1 200 Connection estabilished\n\n')
enc_req = conn.recv(9999) #this gets an encrypted request
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #plaintext client 
client.connect((host, 443)) #connect to chosen host 
client.send(enc_req)
resp1 = client.recv(9999) #this gets something unreadable (encrypted?)
#could it be the certificate?

#now what?

Is the resp1 I'm getting the certificate? And what do I need to do after that? (Or, which is the same, what does usually happens next with https?)

P.S. I know the question is somewhat generic, but please don't judge me too harshly. I've tried researching on the web but all I keep finding is the encryption method used for ssl. I really don't know how to proceed.

2条回答
手持菜刀,她持情操
2楼-- · 2019-07-27 08:08

I haven't tested this code (and it's mainly pseudo code), but this should give you an idea of what you need to do.

conn, addr = server.accept()
request = conn.recv(9999) #get a CONNECT request
# Here, parse the CONNECT string and get the host and port (not sure if you were doing that already.

# Then, try to connect *before* you tell the client the connection was established (in case it fails)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #plaintext client 
client.connect((host, 443)) #connect to chosen host 

conn.send(b'HTTP/1.1 200 Connection estabilished\n\n')

# Then loop until the connections are closed.
while True:
    # Read from the client, send the data to the server.
    enc_req = conn.recv(9999) #this gets an encrypted request
    client.send(enc_req)

    # Read from the server, send the data to the client.
    resp1 = client.recv(9999) #this gets something unreadable (encrypted?)
    #could it be the certificate?
    #now what?
    # The first time it's certainly the Client Hello message, not encrypted, but in a binary format indeed.
    # Just send everything you've just read to the server.
    conn.send(resp1)

This is just a quick overview of the idea of the loop you need to write. In reality, you may be able to process both in parallel. You'd also want to be a bit more careful when closing the connection (allowing it to happen in any order while still relaying the last data sent by either party).

查看更多
不美不萌又怎样
3楼-- · 2019-07-27 08:19

As mentioned in the comments, a proxy handling encrypted end-to-end traffic can only pass it on.

Here is a fully working proxy written using circuits that has been fully tested with passing and proxying SSH traffic so it should work equally as well as a pass-through TCP proxy even if SSL is involved:

#!/usr/bin/env python

from uuid import uuid4 as uuid

from circuits import Component
from circuits.net.events import close, connect, write
from circuits.net.sockets import TCPClient, TCPServer


class Client(Component):

    channel = "client"

    def init(self, sock, host, port, channel=channel):
        self.sock = sock
        self.host = host
        self.port = port

        TCPClient(channel=self.channel).register(self)

    def ready(self, *args):
        self.fire(connect(self.host, self.port))

    def disconnect(self, *args):
        self.fire(close(self.sock), self.parent.channel)

    def read(self, data):
        self.fire(write(self.sock, data), self.parent.channel)


class Proxy(Component):

    channel = "server"

    def init(self, bind, host, port):
        self.bind = bind
        self.host = host
        self.port = port

        self.clients = dict()

        TCPServer(self.bind).register(self)

    def connect(self, sock, host, port):
        channel = uuid()

        client = Client(
            sock, self.host, self.port, channel=channel
        ).register(self)

        self.clients[sock] = client

    def disconnect(self, sock):
        client = self.clients.get(sock)
        if client is not None:
            client.unregister()
            del self.clients[sock]

    def read(self, sock, data):
        client = self.clients[sock]
        self.fire(write(data), client.channel)


app = Proxy(("0.0.0.0", 3333), "127.0.0.1", 22)

from circuits import Debugger
Debugger().register(app)

app.run()
查看更多
登录 后发表回答