Я бы хотел вручную (используя модули socket и ssl ) сделать запрос HTTPS
через прокси-сервер, который сам использует HTTPS
.
Я могу выполнить начальный CONNECT
обмен просто отлично:
import ssl, socket
PROXY_ADDR = ("proxy-addr", 443)
CONNECT = "CONNECT example.com:443 HTTP/1.1\r\n\r\n"
sock = socket.create_connection(PROXY_ADDR)
sock = ssl.wrap_socket(sock)
sock.sendall(CONNECT)
s = ""
while s[-4:] != "\r\n\r\n":
s += sock.recv(1)
print repr(s)
Приведенный выше код печатает HTTP/1.1 200 Connection established
плюс несколько заголовков, что я и ожидаю.Так что теперь я должен быть готов сделать запрос, например
sock.sendall("GET / HTTP/1.1\r\n\r\n")
, но приведенный выше код возвращает
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>400 Bad Request</title>
</head><body>
<h1>Bad Request</h1>
<p>Your browser sent a request that this server could not understand.<br />
Reason: You're speaking plain HTTP to an SSL-enabled server port.<br />
Instead use the HTTPS scheme to access this URL, please.<br />
</body></html>
Это также имеет смысл, поскольку мне все еще нужно выполнить SSL-рукопожатие сexample.com
сервер, к которому я туннелирую.Однако если вместо немедленной отправки запроса GET
я скажу
sock = ssl.wrap_socket(sock)
, чтобы выполнить рукопожатие с удаленным сервером, то я получу исключение:
Traceback (most recent call last):
File "so_test.py", line 18, in <module>
ssl.wrap_socket(sock)
File "/usr/lib/python2.6/ssl.py", line 350, in wrap_socket
suppress_ragged_eofs=suppress_ragged_eofs)
File "/usr/lib/python2.6/ssl.py", line 118, in __init__
self.do_handshake()
File "/usr/lib/python2.6/ssl.py", line 293, in do_handshake
self._sslobj.do_handshake()
ssl.SSLError: [Errno 1] _ssl.c:480: error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol
Так как можноЯ делаю SSL-рукопожатие с удаленным example.com
сервером?
РЕДАКТИРОВАТЬ: Я почти уверен, что до моего второго вызова wrap_socket
дополнительные данные недоступны, потому что sock.recv(1)
блокирует бесконечно.*