Requests: TLS-SNI-Unterstützung

Erstellt am 1. Aug. 2012  ·  46Kommentare  ·  Quelle: psf/requests

Es scheint, dass ich Probleme bei der Verwendung von Anforderungen mit Servern habe, die TLS-SNI-Unterstützung benötigen. Wann werden Anfragen diese Funktion haben? Ist das geplant?

Vielen Dank,
--RAM

Hilfreichster Kommentar

Dies ist in request/packages/urllib3/contrib/pyopenssl.py angegeben :

  • pyOpenSSL (getestet mit 0.13)
  • ndg-httpsclient (getestet mit 0.3.2)
  • pyasn1 (getestet mit 0.1.6)

(Oder Python 3.2 oder höher, was immer funktioniert)

Alle 46 Kommentare

Nicht möglich in Python 2.x auf dem SSL-Modul der stdlib.

Twisted hat es, oder? Vielleicht Zeit, sich auf pyopenssl oder ein anderes SSL-Modul zu verlassen?

Es gibt eine Pull-Anfrage für urllib3, die SNI-Unterstützung für Py32+ hinzufügt, aber noch Testabdeckung benötigt. https://github.com/shazow/urllib3/pull/89

shzow: Danke für den Hinweis. Ich verwende leider Twisted/Flask, was bedeutet, dass ich bei 2.7 feststecke. Twisted scheint so etwas tun zu können, aber ich habe keine Beispiele gesehen, und es bräuchte pyopenssl + Twisted-Dekodierung, um dies zu tun. Bin auch kein Experte, um das durchzuziehen. Denken Sie an dieser Stelle nur daran, ein Befehlszeilendienstprogramm wie wget einzubinden ... :(

PyOpenSSL sollte es auf 2.x tun können. Es besteht also Hoffnung.

Ich könnte es mit pyopenssl zum Laufen bringen. Aber es fällt mir immer noch schwer, es richtig zu machen. http://pbin.be/show/719/ -- Art von Arbeiten. Aber dann muss man eine API darauf bauen, damit sie nützlich ist. Ich kann immer noch nicht herausfinden, wie man den richtigen Kontext an Agent weitergibt.

Lukasa: Wurde das gelöst?

Nein. Wir sind auf shazow/urllib3#89 gesperrt.

Zusammengeführt. Fortfahren. :)

Beachten Sie, dass es derzeit nur auf Py32+ unterstützt wird. Sollte aber für den Anfang reichen.

Eine weitere faire Warnung: Einige Tests auf Py32 schlagen derzeit auf urllib3 master fehl. Etwas Hilfe bei der Behebung dieses Problems wäre sehr willkommen (und könnte diese Funktionalität beeinträchtigen): https://github.com/shazow/urllib3/issues/128

funktioniert für mich auf archlinux x64 auf py26, py27, py32, py33

Ah, ich hätte qualifizieren sollen, dass dies auf OSX ist. Abschaum OSX.

t-8ch: Bestehen die sni-Tests für Sie auf py26/27/32 und 33?

Die SNI-Tests werden nicht einmal auf py2 ausgeführt, aber auf py32 und py33 funktioniert es.
Es gibt keine Möglichkeit, SNI mit dem SSL-Modul der Standardbibliothek vor py32 auszuführen.

@shazow : Vermutlich haben Sie kein Interesse daran, urllib3 von PyOpenSSL abhängig zu machen?

Ich würde mich freuen, eine separate Bibliothek zu haben, die SSL über PyOpenSSL-Unterstützung zu urllib3 hinzufügt.

Es sieht so aus, als würde @t-8ch es mit der Arbeit an urllib3 aus dem Park werfen. Ich werde ihn uns sagen lassen, wann das geschlossen werden kann.

urllib3 bietet optionale Unterstützung für SNI mit Python2, allerdings mit einigen optionalen Abhängigkeiten. (Siehe urllib3#156 ).

Ich glaube, das sollte funktionieren mit:

from requests.packages.urllib3.contrib import pyopenssl
pyopenssl.inject_into_urllib3

Nach dem Hinzufügen zu packages in setup.py

requests.packages.urllib3.contrib

Beachten Sie, dass das Paket contrib standardmäßig nicht importiert wird.

Grundsätzlich gibt es zwei Alternativen, um SNI in Anfragen zu aktivieren:

  • Erstellen Sie eine Funktion zum manuellen Aktivieren von SNI, die im Wesentlichen den obigen Code ausführt. (Der Nachteil ist, dass Benutzer die SNI-Unterstützung explizit aktivieren müssen).
  • Versuchen Sie, die Voraussetzungen zu importieren. Falls vorhanden, aktivieren Sie SNI, andernfalls nicht.

Ich habe kein Problem damit, eine der beiden Alternativen zu implementieren, obwohl ich lieber wissen würde, welche für Anfragen die bevorzugte wäre. Ich persönlich stimme für die zweite Alternative.

Übrigens: Können wir das Problem jetzt wieder öffnen, da wir Unterstützung von urllib3 haben?

Ich bevorzuge eigentlich ersteres, weil die Leute, die es brauchen, diejenigen sind, die wissen, dass sie es brauchen werden, und es sind wenige genug, um nicht zu viele Beschwerden zu verursachen. Wenn wir jedoch mit der bestehenden API konsistent bleiben, wäre letztere der Weg, sie zu implementieren. Derzeit stellt urllib3 (und Anfragen) die API zum Senden von HTTPS-Anfragen ohne das vorhandene SSL-Modul bereit, schlägt jedoch fehl, wenn das SSL-Modul nicht verfügbar ist. Mit anderen Worten, die API ist vorhanden und Sie können sie verwenden, aber sie funktioniert einfach nicht und wird durch eine Ausnahme angezeigt.

Die Wiedereröffnung liegt bei @kennethreitz. Das Problem (bei all dem) ist natürlich, dass wir derzeit einen Feature-Freeze (#1165, #1168) haben, daher bin ich mir nicht sicher, ob sich die Arbeit überhaupt lohnt, da sie möglicherweise nicht akzeptiert wird.

Lassen Sie es mich etwas klarer sagen: Was ich mit der zweiten Alternative meinte, war "Versuchen Sie, SNI zu verwenden, wenn die optionalen Deps verfügbar sind, aber verwenden Sie immer noch SSL, da wir es immer haben, sie sind es nicht.". Dies sollte nichts bisher Bestehendes zerstören.

Was die Wiedereröffnung (oder nicht) des Problems angeht, sollte dieses Problem IMHO nicht auf die leichte Schulter genommen werden. Anfragen können ohne SNI-Unterstützung für viele Szenarien nutzlos werden. Insbesondere werden mehrere Domänen auf einem einzigen IPv4-Host ohne SNI unmöglich. Und zusätzliche IPv4-Adressen kommen für viele Nutzer (aus Kostengründen) nicht in Frage.

Auf jeden Fall ist dies halb Funktion, halb Fehler, obwohl ich auf die Antwort von @kennethreitz bezüglich der Wiedereröffnung des Problems

Hugo: Ich habe gerade pip install -U-Anfragen durchgeführt, und wenn ich contrib nicht importieren kann.
Wie behebe ich das? (Importfehler: Kein Modul namens contrib).

Am Fr, 3. Mai 2013 um 13:12 Uhr, Hugo Osvaldo Barrera <
[email protected]> schrieb:

urllib3 bietet optionale Unterstützung für SNI mit Python2, allerdings mit einigen wenigen
optionale Abhängigkeiten. (Siehe urllib3#156https://github.com/shazow/urllib3/pull/156
).

Ich glaube, das sollte funktionieren mit:

from request.packages.urllib3.contrib import pyopenssl
pyopenssl.inject_into_urllib3

Beachten Sie, dass das contrib-Paket standardmäßig nicht importiert wird.

Grundsätzlich gibt es zwei Alternativen, um SNI in Anfragen zu aktivieren:

  • Erstellen Sie eine Funktion zum manuellen Aktivieren von SNI, die im Wesentlichen das oben genannte ausführt
    Code. (Der Nachteil ist, dass Benutzer SNI explizit aktivieren müssen
    Unterstützung).
  • Versuchen Sie, die Voraussetzungen zu importieren. Falls vorhanden, aktivieren Sie SNI, sonst
    nicht.

Ich habe kein Problem damit, eine der beiden Alternativen zu implementieren, obwohl ich es vorziehen würde
um zu wissen, welches für Anfragen am besten geeignet ist. Ich persönlich stimme für
die zweite Alternative.


Antworten Sie direkt auf diese E-Mail oder zeigen Sie sie auf Gi tHub anhttps://github.com/kennethreitz/requests/issues/749#issuecomment -17406518
.

Die setup.py von request enthält dieses Paket nicht (die Quelle ist dort, aber es wird bei der Installation/Verpackung ausgeschlossen), daher ist es nicht installiert, deshalb habe ich Folgendes erwähnt:

Nachdem Sie dies zu packages in setup.py hinzugefügt haben
request.packages.urllib3.contrib

Sie müssen grundsätzlich von der Quelle installieren.
Schauen Sie sich meinen Pull-Request an, wenn Sie daran interessiert sind. Damit diese Arbeit funktioniert, sind es nur ein paar Zeilen. :)

"Versuchen Sie, SNI zu verwenden, wenn die optionalen Deps verfügbar sind, aber verwenden Sie trotzdem SSL, da wir es immer haben, dies ist nicht der Fall."

SSL ist jedoch nicht immer vorhanden. Das war mein Punkt. Derzeit versuchen wir es zu verwenden, scheitern jedoch hart und schnell, wenn wir es nicht haben und ein Benutzer versucht, eine https-Anfrage zu stellen. So wie Sie es beschrieben hatten, hatte ich jedoch den Eindruck, dass SNI vom Benutzer verlangen würde, einige zusätzliche Informationen an urllib3 weiterzugeben, und Sie konzentrierten sich nur auf die Einrichtung dafür. Wenn nur #1347 erforderlich ist, stehe ich zu 100% dahinter.

Es wäre wirklich schön, wenn dies die Standardeinstellung wäre (SNI-Support) und Anfragen
funktioniert einfach ohne zusätzlichen Code oder Setup von der Quelle. Für urllib3 sind es 2
Zeilen von Code. Warum fügen Sie das nicht einfach zu Anfragen hinzu. Träume ich Tag? :)

Am Freitag, den 3. Mai 2013 um 22:43 Uhr schrieb Ian Cordasco [email protected] :

"Versuchen Sie, SNI zu verwenden, wenn die optionalen Deps verfügbar sind, aber verwenden Sie trotzdem SSL als
wir haben es immer, sie sind es nicht."

SSL ist jedoch nicht immer vorhanden. Das war mein Punkt. Aktuell versuchen wir es und
Verwenden Sie es, aber scheitern Sie hart und schnell, wenn wir es nicht haben und ein Benutzer versucht, es zu machen
eine https-Anfrage. So wie du es beschrieben hast, war ich aber unter der
impression SNI würde erfordern, dass der Benutzer einen zusätzlichen Begriff an urllib3 weitergibt
und Sie haben sich nur auf das Setup dafür konzentriert. Wenn das alles nötig ist
ist #1347 https://github.com/kennethreitz/requests/issues/1347 dann bin ich
100% dahinter.


Antworten Sie direkt auf diese E-Mail oder zeigen Sie sie auf Gi tHub anhttps://github.com/kennethreitz/requests/issues/749#issuecomment -17426626
.

@pythonmobile dreht ein Kreisel. Wenn es nicht aufhört, sich zu drehen, träumst du.

inception

Hinterlassen Sie einen Kommentar für andere, die möglicherweise auf das gleiche Problem wie ich stoßen:
Wenn Sie Probleme mit sicheren Anfragen mit der Bibliothek requests , insbesondere wenn Sie versuchen, eine auf Google App Engine gehostete App zu erreichen, kann dies der Grund sein. Der Fehler, den ich sah, war "EOF ist unter Verletzung des Protokolls aufgetreten". Um dies zu diagnostizieren, versuchen Sie, denselben Host mit s_client treffen (ersetzen Sie example.com durch den fraglichen Host):

openssl s_client -connect example.com:443
openssl s_client -connect example.com:443 -servername example.com

Wenn der erste Befehl mit "Handshake-Fehler" fehlschlägt und der zweite erfolgreich ist, versuchen Sie, einen Server zu erreichen, der SNI verwendet. Der vorliegende Thread enthält einige gute Informationen, wie man requests in dieser Situation zum Laufen bringt. Ich habe versucht, from requests.packages.urllib3.contrib import pyopenssl in ipython auszuführen, und ich fuhr fort, alle Importfehler von pip zu installieren. YMMV.

@mshang Version 1.2.3 sollte dies bereits für Sie erledigen; Bist du sicher, dass du diese Version verwendest?

@hobarrera Ja, ich verwende 1.2.3. requests.packages.urllib3.contrib war da, aber diese Import-Anweisungen verursachten immer noch eine Reihe von Importfehlern. Ich musste ndg-httpsclient installieren und vergesse was noch.

Richtig. Requests versucht nur, die benötigten Module zu importieren, und wenn es nicht aufgeben kann, setzt es sein Leben fort. Es kann jedoch eine gute Idee sein, zu dokumentieren, was Sie benötigen, um SNI mit Anfragen zu verwenden.

Dies ist in request/packages/urllib3/contrib/pyopenssl.py angegeben :

  • pyOpenSSL (getestet mit 0.13)
  • ndg-httpsclient (getestet mit 0.3.2)
  • pyasn1 (getestet mit 0.1.6)

(Oder Python 3.2 oder höher, was immer funktioniert)

Scheint, als ob beide Anfragen und urllib3 derzeit für SNI defekt sind. Einer
Problem ist, dass wenn man timeout=5.0 hinzufügt, der Code sich anders verhält als
ohne Auszeit. Das zweite Problem sind Domänen, die nicht existieren.
Die Tests müssen mehr SNI-Domänen hinzufügen als nur abhängig von
vertex/httpbin/. Beide spiegeln die SNI-Nutzung überhaupt nicht wider.

Am Mo, 10.06.2013 um 4:57 Uhr, Thomas Weißschuh
[email protected] schrieb :

Dies ist in request/packages/urllib3/contrib/pyopenssl angegeben. pyhttps://github.com/kennethreitz/requests/blob/master/requests/packages/urllib3/contrib/pyopenssl.py
:

  • pyOpenSSL (getestet mit 0.13)
  • ndg-httpsclient (getestet mit 0.3.2)
  • pyasn1 (getestet mit 0.1.6)

(Oder Python 3.2 oder höher, was immer funktioniert)


Antworten Sie direkt auf diese E-Mail oder zeigen Sie sie auf Gi tHub anhttps://github.com/kennethreitz/requests/issues/749#issuecomment -19187417
.

@pythonmobile Wenn dies der Fall ist und Sie einen gut reproduzierbaren Testfall haben, öffnen Sie bitte ein Problem, in dem dies auf urllib3 hervorgehoben wird. Requests hat keinen SNI-spezifischen Code (soweit ich weiß), also wird ein Fix dort auch uns reparieren.

Es sei denn, urllib3 ist bereits behoben, was heutzutage häufig vorkommt. Shazow_et. al._ sind ziemlich genial. @t-8ch, habt ihr das schon gesehen/behoben?

Ich denke, wenn wir die Tests in Anfragen schreiben, sind sie einfacher zu schreiben und zu testen, obwohl dies nur bedeutet, dass hauptsächlich urllib3-Code getestet wird. Auf diese Weise ist es einfacher, bei jedem Import von urllib3 in Anfragen zu überprüfen, ob sni kaputt ist oder nicht und einen Alarm auszulösen. Ich werde die Anfragetests bald schreiben.

Entschuldigung @pythonmobile , ich stimme nicht zu. =)

SNI ist explizit urllib3-Funktionalität. Wenn SNI in urllib3 defekt ist, sollten Sie diesem Projekt unbedingt einen Fix, einen Test oder zumindest einen Fehlerbericht zur Verfügung stellen. Wenn dieses Projekt behoben ist, werden auch Anfragen auf magische Weise behoben (wenn wir das nächste Mal urllib3 aktualisieren, was wir ziemlich häufig tun). =)

Während mehr Tests für Anfragen sicherlich nicht schaden würden , müssen Sie, wie

Wir haben bereits viele ähnliche Tests, pingen Sie mich an, wenn Sie Hilfe benötigen.

Es scheint, dass sich das Timeout-Verhalten von pyOpenSSL von dem von pyOpenSSL unterscheidet
Standard-SSL-Modul:

from OpenSSL import SSL
import socket
import ssl

sock = socket.create_connection(('httpbin.org', 443), timeout=4.0)
ssl_sock = ssl.wrap_socket(sock)
ssl_sock.send('GET /ip HTTP/1.1\r\nHost: httpbin.org\r\n\r\n')
print(ssl_sock.recv(10000))

ctx = SSL.Context(SSL.TLSv1_METHOD)
sock = socket.create_connection(('httpbin.org', 443), timeout=4.0)
ctn = SSL.Connection(ctx, sock)
ctn.set_connect_state()

ctn.send('GET /ip HTTP/1.1\r\nHost: httpbin.org\r\n\r\n')
print(sock.read(10000))

Dies wirft ein WantReadError , das gleiche, das auch von urllib3 ausgeworfen wird
bei der Angabe eines Timeouts.

Die Dokumentation hat
dies zu dem fehler:

The operation did not complete; the same I/O method should be called again
later, with the same arguments. Any I/O method can lead to this since new
handshakes can occur at any time.

The wanted read is for dirty data sent over the network, not the clean data
inside the tunnel. For a socket based SSL connection, read means data coming at
us over the network. Until that read succeeds, the attempted
OpenSSL.SSL.Connection.recv, OpenSSL.SSL.Connection.send, or
OpenSSL.SSL.Connection.do_handshake is prevented or incomplete. You probably
want to select() on the socket before trying again. 

Ich weiß nicht, wie die Zeitüberschreitung behandelt werden soll. Macht die Steckdose magisch
Erinnern Sie sich an die Zeitüberschreitung bei Aufrufen von select() oder ist dies die Aufgabe von
urllib3?
Die Zeitüberschreitung von Hand zu verfolgen klingt nicht wirklich lustig.

@pythonmobile Was meinst du mit nicht vorhandenen Domains. Ich kann dir nicht folgen.

@pythonmobile Könnten Sie die Änderungen von shazow/urllib3#233 ausprobieren und prüfen, ob der Code mit pyopenssl und Timeouts funktioniert?

@t-8ch @pythonmobile : Könnt ihr euch auch diesen Thread anschauen: https://github.com/kennethreitz/requests/issues/1522#issuecomment -22443282

Es wäre schön, diese Anfragen in einem Komponententest innerhalb von urllib3 oder Anfragen zu erhalten.

Das Problem dabei, diese als Komponententest zu erhalten, besteht darin, dass sie nur in sehr bestimmten Konfigurationen angezeigt werden. Zum Beispiel konnte ich weder die zweite Hälfte dieses Problems noch #1522 auf einem meiner Systeme reproduzieren, egal ob es sich um Windows, OS X oder Ubuntu handelt. Deshalb habe ich @pythonmobile um einen reproduzierbaren Unit-Test gebeten. Wenn wir einen finden, können wir uns dagegen entwickeln, ansonsten hoffen wir, dass @t-8ch weiterhin ein Genie ist und alle unsere Probleme auf magische Weise bei urllib3 löst.

NB: @t-8ch, ich glaube, ich danke dir nicht genug für deine Arbeit, sowohl hier als auch bei urllib3 . Du bist unglaublich. =D :Kuchen: :Ananas: :Banane: :Keks: :Bier:

@lukasa Danke :smile: Ich denke, ich könnte mich irgendwann in der Zukunft zu AUTHORS.txt hinzufügen.

@t-8ch Mach es. :+1:

Die Änderungen in shazow/urllib3#233 (jetzt in den urllib3-Master gezogen) beheben das Problem für mich ( SSLError('bad handshake', WantReadError()) ), das bei einigen URLs manchmal in einigen Konfigurationen auftrat :rage4:. Können wir dies in den Request-Master ziehen?

@rcoup Wir werden eine aktuelle Version in Requests

Ich verwende Python 2.7.6 und kann pyOpenSSL nicht installieren. Ich habe die Workarounds im htis-Post ausprobiert -> https://stackoverflow.com/questions/18578439/using-requests-with-tls-doesnt-give-sni-support/18579484#18579484

Ich kann auch nicht von Python upgraden. Irgendwelche anderen Lösungen?

Ich bitte wir, die bedingungslose Verwendung (falls vorhanden) von "inject_into_urllib3()" zu überdenken.

Vor 7 Jahren hinzugefügt, war das Ziel, "SNI-Unterstützung für Python 2 hinzuzufügen".

"urllib3.contrib.pyopenssl.inject_into_urllib3()" wird beschrieben zu "Monkey-patch urllib3 with PyOpenSSL-backed SSL-support.":
(https://github.com/urllib3/urllib3/blob/master/src/urllib3/contrib/pyopenssl.py)

Rechtfertigung:
1: Sicherheit/Stabilität: Monkey Patching zum Austauschen der Standardbibliotheksnutzung durch eine Drittanbieterbibliothek sollte wohl chirurgischer sein, insbesondere für SSL. Wenn der Patch für die Unterstützung von Python2 vorgesehen ist, suchen Sie zumindest nach einer Hauptversion. Oder noch besser, prüfen Sie, ob SNI-Unterstützung bereits vorhanden ist ssl.HAS_SNI .

2: Unnötig: Seit dem 10. Dezember 2014 wurde das gesamte SSL-Modul von Python 3.4 für Python 2.7.9 zurückportiert. Zur Begründung siehe PEP 466. https://www.python.org/downloads/release/python-279/. Dies ermöglicht die SNI-Unterstützung in der Standardbibliothek für > v2.7.9

3: Unflexibel: Wie implementiert, gibt es keine Möglichkeit, dieses Verhalten zu deaktivieren. Die einzige Option, um zu verhindern, dass requests den pyopenssl-Kontext verwendet, besteht darin, pyopenssl für meine gesamte Python-Umgebung zu deinstallieren.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen