Конвертировать 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 (адресной строке). В противном случае веб-браузер выдаст предупреждения безопасности.
Есть способы обойти это, например, генерировать сертификаты на лету, но вам нужно, чтобы корневой сертификат был доверенным в браузере.