HTTPS-proxy-tunneling mit dem ssl-Modul
Möchte ich manuell (über die Buchse und ssl Module) eine HTTPS
Anfrage über einen proxy, welcher selbst verwendet HTTPS
.
Ich kann die ersten CONNECT
exchange gut:
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)
Der obige code druckt HTTP/1.1 200 Connection established
plus einige Header, die ist, was ich erwarte. So, jetzt sollte ich bereit sein, die Anfrage zu machen, z.B.
sock.sendall("GET /HTTP/1.1\r\n\r\n")
aber der obige code gibt
<!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>
Dies macht Sinn, auch, da ich noch tun müssen, um einen SSL-handshake mit dem example.com
server auf den ich bin tunneling. Jedoch, wenn anstatt sofort senden die GET
Anfrage ich sagen
sock = ssl.wrap_socket(sock)
zu tun, den Handschlag mit dem remote-server, dann bekomme ich eine exception:
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
So, wie kann ich den SSL-handshake mit dem remote - example.com
server?
EDIT: ich bin mir ziemlich sicher, dass keine weiteren Daten verfügbar sind, bevor meine zweite Aufruf wrap_socket
da ruft sock.recv(1)
Blöcke auf unbestimmte Zeit.
- meine grobe Vermutung ist, dass
ssl.wrap_socket
kümmert sich um socket-Verbindung Stand. in der Regel würden Sie socket erzeugen, dann wickeln Sie es, dann verbinden. Hier legen Sie die Buchse, verbinden, dann wickeln. vielleicht ssl ist nur verwirrt von bereits verbundenen zugrunde liegenden socket-Zustand. github.com/kennethreitz/requests/blob/... - hey, haben Sie noch Glück? Ich komme bei dem gleichen problem, aber auch nichts gefunden...
Du musst angemeldet sein, um einen Kommentar abzugeben.
Dieser sollte funktionieren, wenn der CONNECT-string wird wie folgt neu gefasst:
Nicht sicher, warum dies funktioniert, aber vielleicht hat es etwas zu tun mit dem proxy bin ich mit. Hier ein Beispiel-code:
Hinweis, wie der sockel wird zuerst geöffnet und dann offen-Buchse platziert im SSL-Kontext. Dann habe ich manuell initialisieren der SSL-handshake. Und Ausgabe:
Es basiert auf pyOpenSSL, weil ich brauchte, zu Holen ungültige Zertifikate zu und Python integrierten ssl-Modul wird immer versuchen, um das Zertifikat zu überprüfen, wenn es empfangen.
ssl.wrap_socket
?Error: [('SSL routines', 'SSL23_GET_SERVER_HELLO', 'unknown protocol')]
und keine Binär-Müll in ssl-Tiefe-1 Ausgang. Ich vermute, dass anstelle von Geschenkpapier Daten in SSL zweimal, OpenSSL verwendet das zugrunde liegende socket/fd und nur wraps Daten einmal.Ausgehend von der API von OpenSSL und GnuTLS-Bibliothek, stapeln ein SSLSocket auf einen SSLSocket ist tatsächlich nicht unkompliziert möglich, da Sie spezielle lese - /schreib-Funktionen, die zum implementieren der Verschlüsselung, die Sie nicht verwenden, selbst wenn die Verpackung einer bereits bestehenden SSLSocket.
Der Fehler wird daher verursacht durch die innere SSLSocket direkt Lesen aus dem system-sockel und nicht von der äußeren SSLSocket. Dieser endet mit der übermittlung von Daten, die nicht Eigentum der äußeren SSL-session, die enden schlecht und sicher nie wieder eine gültige ServerHello.
Abschluss von diesem, ich würde sagen, es gibt keinen einfachen Weg das umzusetzen, was Sie (und eigentlich auch mich) möchte erreichen.
socket.socketpair
😉twisted
- Paket wird für SSL-Unterstützung-in-SSL über benutzerdefinierteBIO
in seiner SSL/TLS-Modul, aber das ist eine Menge von Abhängigkeiten.Es klingt nicht so, es gibt nichts falsch mit dem, was Sie tun, es ist sicherlich möglich, rufen Sie
wrap_socket()
auf eine vorhandeneSSLSocket
.'Unknown protocol' Fehler auftreten können (unter anderem), ob es zusätzliche Daten darauf warten, gelesen zu werden auf die sockel an der Stelle, die Sie anrufen
wrap_socket()
zum Beispiel eine zusätzliche\r\n
oder eine HTTP-Fehlermeldung (wegen eines fehlenden cert auf dem server, zum Beispiel). Sind Sie sicher, Sie haben alles gelesen, was verfügbar ist an diesem Punkt?Wenn Sie können erzwingen, dass der erste SSL-Kanal zu verwenden, ein "einfacher" RSA-Verschlüsselung (D. H. nicht-Diffie-Hellman), dann Sie können möglicherweise verwenden Sie Wireshark, um zu entschlüsseln, den stream, um zu sehen, was Los ist.
sock.recv(1)
dann ist es blockiert auf unbestimmte Zeit. Aber danke für die Bestätigung, dass ich Doppel-wrap-a-Buchse. Ich kann nicht ändern, der server SSL-Einstellungen, aber ich Schätze die Wireshark-Vorschlag - bitte lassen Sie mich wissen, wenn Sie irgendwelche anderen Ideen.Endlich hab ich irgendwo Erweiterung auf @kravietz und @02strich Antworten.
Hier ist der code
Nicht Verstand benutzerdefinierte
cihpers=
, dass nur, weil ich nicht wollte, Umgang mit Zertifikaten.Und es gibt Tiefe-1 ssl-Ausgabe, zeigt
CONNECT
, meine Antwort daraufssagd
und Tiefe-2 ssl-Aushandlung und Binär-Müll:Gebäude auf @kravietz Antwort. Hier ist eine version, die funktioniert in Python ist3 durch einen Squid-proxy:
Funktioniert dies in Python 2.