Конвертировать HTTP-прокси в HTTPS-прокси в Twisted

Недавно я поиграл с прокси HTTP в витой. После долгих проб и ошибок я думаю, что наконец-то у меня что-то работает. Однако я хочу знать, как, если это возможно, расширить этот прокси-сервер, чтобы он также мог обрабатывать HTTPS-страницы? Вот что у меня так далеко:

from twisted.internet import reactor
from twisted.web import http
from twisted.web.proxy import Proxy, ProxyRequest, ProxyClientFactory, ProxyClient



class HTTPProxyClient(ProxyClient):
    def handleHeader(self, key, value):
        print "%s : %s" % (key, value)
        ProxyClient.handleHeader(self, key, value)

    def handleResponsePart(self, buffer):
        print buffer
        ProxyClient.handleResponsePart(self, buffer)

class HTTPProxyFactory(ProxyClientFactory):
    protocol = HTTPProxyClient

class HTTPProxyRequest(ProxyRequest):
    protocols = {'http' : HTTPProxyFactory}

    def process(self):
        print self.method
        for k,v in self.requestHeaders.getAllRawHeaders():
            print "%s : %s" % (k,v)
        print "\n \n"

        ProxyRequest.process(self)

class HTTPProxy(Proxy):

    requestFactory = HTTPProxyRequest


factory = http.HTTPFactory()
factory.protocol = HTTPProxy

reactor.listenSSL(8001, factory)
reactor.run()

Как показывает этот код, сейчас для примера я просто распечатываю все, что происходит через соединение. Можно ли обрабатывать HTTPS с одинаковыми классами? Если нет, то как мне реализовать такую ​​вещь?

2 ответа

Решение

Если вы хотите подключиться к веб-сайту HTTPS через HTTP-прокси, вам нужно использовать CONNECT HTTP-глагол (потому что именно так работает прокси для HTTPS). В этом случае прокси-сервер просто подключается к целевому серверу и передает все, что отправлено сервером, обратно в сокет клиента (и наоборот). В этом случае нет никакого кеширования (но вы можете регистрировать хосты, к которым вы подключаетесь).

Обмен будет выглядеть так (клиент на прокси):

C->P: CONNECT target.host:443 HTTP/1.0
C->P:

P->C: 200 OK
P->C: 

После этого прокси-сервер просто открывает простой сокет для целевого сервера (пока без HTTP или SSL/TLS) и передает все между исходным клиентом и целевым сервером (включая рукопожатие TLS, которое инициирует клиент). Клиент обновляет имеющийся у него сокет до прокси-сервера, чтобы использовать TLS/SSL (путем запуска рукопожатия SSL/TLS). Как только клиент прочитал строку состояния "200", для клиента все равно, что он установил соединение с целевым сервером напрямую.

Я не уверен насчет скрученности, но хочу предупредить вас, что если вы внедрите HTTPS-прокси, веб-браузер будет ожидать, что SSL-сертификат сервера будет соответствовать доменному имени в URL (адресной строке). В противном случае веб-браузер выдаст предупреждения безопасности.

Есть способы обойти это, например, генерировать сертификаты на лету, но вам нужно, чтобы корневой сертификат был доверенным в браузере.

Другие вопросы по тегам