Requests: Soporte TLS SNI

Creado en 1 ago. 2012  ·  46Comentarios  ·  Fuente: psf/requests

Parece que tengo problemas para usar solicitudes con servidores que necesitan soporte TLS SNI. ¿Cuándo tendrán las solicitudes esta función? ¿Es esto algo que está planeado?

Gracias,
--RAM

Comentario más útil

Esto se especifica en request / packages / urllib3 / contrib / pyopenssl.py :

  • pyOpenSSL (probado con 0.13)
  • ndg-httpsclient (probado con 0.3.2)
  • pyasn1 (probado con 0.1.6)

(O python3.2 o superior, que siempre funciona)

Todos 46 comentarios

No es posible en Python 2.x encima del módulo ssl de stdlib.

Twisted lo tiene, ¿verdad? ¿Quizás es hora de depender de pyopenssl o de algún otro módulo ssl?

Hay una solicitud de extracción para urllib3 que agrega soporte SNI para Py32 +, pero aún necesita cobertura de prueba. https://github.com/shazow/urllib3/pull/89

shzow: Gracias por el puntero. Desafortunadamente, estoy usando Twisted / Flask, lo que significa que estoy atascado en 2.7. Twisted parece que puede hacer algo como esto, pero no he visto ejemplos, y necesitaría decodificación pyopenssl + twisted para hacer esto. No soy un experto en ninguno de los dos para lograrlo. En este punto, solo estoy pensando en envolver alguna utilidad de línea de comando como wget ... :(

PyOpenSSL debería poder hacerlo en 2.x. Entonces hay esperanza.

Podría hacerlo funcionar con pyopenssl. Pero todavía estoy teniendo dificultades para hacerlo bien torcido. http://pbin.be/show/719/ - tipo de obras. Pero luego uno tiene que construir una API para que sea útil. Todavía no puedo entender cómo pasar el contexto correcto al agente.

Lukasa: ¿se resolvió esto?

No. Estamos bloqueados en shazow / urllib3 # 89.

Fusionada. Seguir adelante. :)

Tenga en cuenta que solo es compatible con Py32 + por ahora. Sin embargo, debería ser suficiente para empezar.

Otra advertencia justa: algunas pruebas en Py32 están fallando en urllib3 master en este momento. Se agradecería mucho ayuda para resolver esto (y podría afectar esta funcionalidad): https://github.com/shazow/urllib3/issues/128

funciona para mí en archlinux x64 en py26, py27, py32, py33

Ah, debería haber calificado que esto está en OSX. Scumbag OSX.

t-8ch: ¿Están pasando las pruebas sni en py26 / 27/32 y 33 para usted?

Las pruebas SNI ni siquiera se ejecutan en py2, pero en py32 y py33 funciona.
No hay forma de hacer SNI con el módulo ssl de la biblioteca estándar antes de py32.

@shazow : ¿Es de suponer que no tiene interés en hacer que urllib3 dependa de PyOpenSSL?

Me complacería tener una biblioteca separada que agregue SSL a través de la compatibilidad con PyOpenSSL a urllib3.

Parece que @ t-8ch lo está sacando del parque con el trabajo en urllib3. Dejaré que nos diga cuándo se puede cerrar esto.

urllib3 tiene soporte opcional para SNI con python2, aunque con algunas dependencias opcionales. (Ver urllib3 # 156 ).

Creo que esto debería funcionar usando:

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

Después de agregar esto a packages en setup.py

requests.packages.urllib3.contrib

Tenga en cuenta que el paquete contrib no se importa de forma predeterminada.

Básicamente, existen dos alternativas para habilitar SNI en las solicitudes:

  • Crear función para habilitar manualmente SNI que básicamente ejecuta el código anterior. (la desventaja es que los usuarios deberán habilitar explícitamente el soporte SNI).
  • Intente importar los requisitos previos. Si existen, habilite SNI, de lo contrario no lo haga.

No tengo problemas para implementar ninguna de las dos alternativas, aunque preferiría saber cuál sería la preferida para las solicitudes. Yo personalmente voto por la segunda alternativa.

Por cierto: ¿podemos reabrir el problema, ahora que tenemos soporte de urllib3?

De hecho, prefiero lo primero porque las personas que lo necesitan son las que saben que lo necesitarán y son lo suficientemente pocas como para que no cause demasiadas quejas. Sin embargo, si vamos a ser consistentes con la API existente, esta última sería la forma de implementarla. Actualmente, urllib3 (y las solicitudes) proporcionarán la API para enviar solicitudes HTTPS sin el módulo ssl presente, pero fallará en el caso de que el módulo ssl no esté disponible. En otras palabras, la API está ahí y puede usarla, pero simplemente no funcionará y eso se indica mediante una excepción.

En cuanto a reabrir esto, eso depende de @kennethreitz. El problema, por supuesto (con todo esto) es que actualmente estamos bajo una congelación de funciones (# 1165, # 1168), así que no estoy seguro de si vale la pena hacer el trabajo porque podría no ser aceptado.

Permítanme ser un poco más claro: lo que quise decir con la segunda alternativa fue "Intente usar SNI si los departamentos opcionales están disponibles, pero aún use SSL, ya que siempre lo tenemos". Esto no debería romper nada existente hasta ahora.

En cuanto a reabrir (o no) el problema, en mi humilde opinión, este problema no debe tomarse a la ligera. las solicitudes pueden volverse inútiles sin el soporte de SNI para muchos escenarios. En particular, varios dominios en un solo host IPv4 sin SNI se vuelven imposibles. Y las direcciones IPv4 adicionales están fuera de discusión para muchos usuarios (debido a su costo).

En cualquier caso, esto es mitad característica, mitad error, aunque esperaré la respuesta de

Hugo: Acabo de hacer solicitudes pip install -U, y cuando no puedo importar contrib.
¿Cómo arreglo eso? (Importerror: ningún módulo llamado contrib).

El viernes 3 de mayo de 2013 a las 13:12, Hugo Osvaldo Barrera <
[email protected]> escribió:

urllib3 tiene soporte opcional para SNI con python2, aunque con algunos
dependencias opcionales. (Ver urllib3 # 156https: //github.com/shazow/urllib3/pull/156
).

Creo que esto debería funcionar usando:

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

Tenga en cuenta que el paquete contrib no se importa de forma predeterminada.

Básicamente, existen dos alternativas para habilitar SNI en las solicitudes:

  • Crear función para habilitar manualmente SNI que básicamente ejecuta lo anterior
    código. (la desventaja es que los usuarios necesitarán habilitar explícitamente SNI
    apoyo).
  • Intente importar los requisitos previos. Si existen, habilite SNI, de lo contrario
    no lo hagas.

No tengo problemas para implementar ninguna de las dos alternativas, aunque prefiero
para saber cuál sería el preferido para las solicitudes. Yo personalmente voto por
la segunda alternativa.

-
Responda a este correo electrónico directamente o véalo en Gi
.

setup.py de la solicitud no incluye ese paquete (la fuente está allí, pero se excluye al instalar / empaquetar), por lo que no está instalado, por eso mencioné:

Después de agregar esto a packages in setup.py
request.packages.urllib3.contrib

Básicamente, necesitará instalar desde la fuente.
Echa un vistazo a mi solicitud de extracción si estás interesado, hacer que esto funcione es solo un par de líneas. :)

"Intente usar SNI si los departamentos opcionales están disponibles, pero aún use SSL, ya que siempre lo tenemos".

Sin embargo, SSL no siempre está ahí. Ese era mi punto. Actualmente lo intentamos y lo usamos, pero fallamos mucho y rápido si no lo tenemos y un usuario intenta realizar una solicitud https. Sin embargo, de la forma en que lo describió, tenía la impresión de que SNI requeriría que el usuario pasara una noción adicional a urllib3 y usted se estaba enfocando solo en la configuración para ello. Si todo lo que se necesita es el # 1347, entonces estoy 100% detrás de esto.

Sería realmente bueno si este fuera el predeterminado (Soporte SNI) y las solicitudes
simplemente funciona sin ningún código adicional o configuración desde la fuente. Para urllib3 es 2
líneas de código. ¿Por qué no agregar eso a las solicitudes? ¿Estoy soñando despierto? :)

El viernes 3 de mayo de 2013 a las 10:43 p.m., Ian Cordasco [email protected] escribió:

"Intente usar SNI si los departamentos opcionales están disponibles, pero aún use SSL como
siempre tenemos que no lo son ".

Sin embargo, SSL no siempre está ahí. Ese era mi punto. Actualmente intentamos y
usarlo, pero fallará duro y rápido si no lo tenemos y un usuario intenta hacer
una solicitud https. Sin embargo, de la forma en que lo habías descrito, estaba bajo el
impresión SNI requeriría que el usuario pasara alguna noción adicional a urllib3
y te estabas concentrando solo en la configuración para ello. Si todo eso es necesario
es # 1347 https://github.com/kennethreitz/requests/issues/1347 entonces soy
100% detrás de esto.

-
Responda a este correo electrónico directamente o véalo en Gi
.

@pythonmobile gira una peonza. Si no deja de girar, estás soñando.

inception

Dejando un comentario por el bien de otras personas que pueden tener el mismo problema que yo:
Si tiene problemas para realizar solicitudes seguras utilizando la biblioteca requests , en particular cuando intenta acceder a una aplicación alojada en Google App Engine, esta puede ser la razón. El error que estaba viendo era "EOF ocurrió en violación del protocolo". Para diagnosticar esto, intente acceder al mismo host usando s_client (reemplace example.com con el host en cuestión):

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

Si el primer comando falla con "falla en el protocolo de enlace" y el segundo tiene éxito, entonces está intentando acceder a un servidor que usa SNI. El hilo actual tiene buena información sobre cómo hacer que requests funcione en esta situación. Lo que hice fue intentar ejecutar from requests.packages.urllib3.contrib import pyopenssl en ipython, y seguí con pip instalando cualquier error de importación. YMMV.

@mshang La versión 1.2.3 ya debería hacer esto por usted; ¿Estás seguro de que estás ejecutando esa versión?

@hobarrera Sí, estoy ejecutando 1.2.3. requests.packages.urllib3.contrib estaba allí, pero las declaraciones de importación aún arrojaban un montón de errores de importación. Tuve que instalar ndg-httpsclient y olvido qué más.

Correcto. Requests solo intenta importar los módulos necesarios, y si no puede, se da por vencido y continúa con su vida. Sin embargo, podría ser una buena idea documentar lo que necesita para usar SNI con solicitudes.

Esto se especifica en request / packages / urllib3 / contrib / pyopenssl.py :

  • pyOpenSSL (probado con 0.13)
  • ndg-httpsclient (probado con 0.3.2)
  • pyasn1 (probado con 0.1.6)

(O python3.2 o superior, que siempre funciona)

Parece que tanto las solicitudes como urllib3 están rotas para SNI actualmente. Uno
El problema es que si se agrega timeout = 5.0, el código se comporta de manera diferente a
sin tiempo de espera. El segundo problema es con los dominios que no existen.
Las pruebas deben agregar más dominios SNI en comparación con solo dependiendo de
vértice / httpbin /. Ambos no reflejan el uso de SNI en absoluto.

El lunes 10 de junio de 2013 a las 4:57 a.m., Thomas Weißschuh
[email protected]ó :

Esto se especifica en request / packages / urllib3 / contrib / pyopenssl. pyhttps: //github.com/kennethreitz/requests/blob/master/requests/packages/urllib3/contrib/pyopenssl.py
:

  • pyOpenSSL (probado con 0.13)
  • ndg-httpsclient (probado con 0.3.2)
  • pyasn1 (probado con 0.1.6)

(O python3.2 o superior, que siempre funciona)

-
Responda a este correo electrónico directamente o véalo en Gi
.

@pythonmobile Si ese es el caso, y tiene un buen caso de prueba reproducible, abra un problema resaltándolo en urllib3. Las solicitudes no tienen un código específico de SNI (hasta donde yo sé), por lo que una solución allí también nos solucionará.

A menos que urllib3 ya esté arreglado, lo que parece suceder mucho en estos días. Shazow _et. al._ son bastante impresionantes. @ t-8ch, ¿han visto / arreglado esto ya?

Creo que si escribimos las pruebas en solicitudes, son más fáciles de escribir y probar, aunque solo significa que probará principalmente el código urllib3. De esa manera, será más fácil verificar en cada importación de urllib3 en las solicitudes, si sni está roto o no y dar la alarma. Escribiré las pruebas de solicitudes pronto.

Lo siento @pythonmobile , no estoy de acuerdo. =)

SNI es explícitamente una funcionalidad urllib3. Si SNI está roto en urllib3, debe proporcionarle a ese proyecto una solución, una prueba o al menos un informe de error. Cuando se arregle ese proyecto, las solicitudes también se arreglarán mágicamente (la próxima vez que actualicemos urllib3, lo que hacemos con bastante frecuencia). =)

Si bien más pruebas para solicitudes ciertamente no estarían de más, como dijo @Lukasa , deberá escribir una prueba para urllib3 si desea ver que esto realmente se solucione. :)

Ya tenemos muchas pruebas en una línea similar, escríbame si necesita ayuda.

Parece que el comportamiento de tiempo de espera de pyOpenSSL es diferente al de
módulo ssl estándar:

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))

Esto arroja un WantReadError , el mismo que también se arroja desde urllib3
al especificar un tiempo de espera.

La documentación tiene
esto para decir sobre el error:

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. 

No sé cómo se debe manejar el tiempo de espera. ¿El enchufe por arte de magia
recordar el tiempo de espera sobre las invocaciones de select() o es esta la tarea de
urllib3?
Hacer un seguimiento del tiempo de espera a mano no suena muy divertido.

@pythonmobile ¿Qué quieres decir con dominios inexistentes? No puedo seguirte.

@pythonmobile ¿Podrías probar los cambios de shazow / urllib3 # 233 y ver si el código funciona con pyopenssl y timeouts?

@ t-8ch @pythonmobile : ¿Pueden ver este hilo también? https://github.com/kennethreitz/requests/issues/1522#issuecomment -22443282

Sería bueno obtener estas solicitudes en una prueba unitaria dentro de urllib3 o solicitudes.

El problema de obtenerlos como prueba unitaria es que solo aparecen en configuraciones muy específicas. Por ejemplo, nunca he podido reproducir ni la segunda mitad de este problema ni el número 1522 en ninguno de mis sistemas, ya sea Windows, OS X o Ubuntu. Por eso le pedí a @pythonmobile una prueba unitaria reproducible. Si podemos encontrar uno, podemos desarrollar en contra de él, de lo contrario, estamos atascados con la esperanza de que @ t-8ch siga siendo un genio y solucione mágicamente todos nuestros problemas en urllib3 .

NB: @ t-8ch, no creo que le agradezco lo suficiente por su trabajo, tanto aquí como en urllib3 . Eres increíble. = D: pastel:: piña:: plátano:: galleta:: cervezas:

@lukasa Gracias: sonrisa: creo que podría AUTHORS.txt algún momento en el futuro.

@ t-8ch Hazlo. : +1:

Los cambios en shazow / urllib3 # 233 (ahora incluido en urllib3 master) solucionan el problema ( SSLError('bad handshake', WantReadError()) ) que ocurría para algunas URL, algunas veces, en algunas configuraciones: rage4 :. ¿Podemos conseguir esto en el maestro de solicitudes?

@rcoup Incorporaremos una versión actualizada en Requests cuando

Estoy ejecutando Python 2.7.6 y no puedo instalar pyOpenSSL. Probé las soluciones en la publicación htis -> https://stackoverflow.com/questions/18578439/using-requests-with-tls-doesnt-give-sni-support/18579484#18579484

No puedo actualizar también con Python. ¿Alguna otra solución?

Solicito que reconsideremos el uso incondicional (si está presente) de "inject_into_urllib3 ()".

Agregado hace 7 años, el objetivo era "agregar soporte SNI para Python 2"

"urllib3.contrib.pyopenssl.inject_into_urllib3 ()" se describe como "Monkey-patch urllib3 con soporte SSL respaldado por PyOpenSSL":
(https://github.com/urllib3/urllib3/blob/master/src/urllib3/contrib/pyopenssl.py)

Justificación:
1: Seguridad / estabilidad: el parche de mono para cambiar el uso de la biblioteca estándar por una biblioteca de terceros debería posiblemente ser más quirúrgico, especialmente para ssl. Si el parche es compatible con Python2, al menos busque una versión principal. O mejor aún, verifique si el soporte SNI ya está presente ssl.HAS_SNI .

2: Innecesario: A partir del 10 de diciembre de 2014, la totalidad del módulo ssl de Python 3.4 se ha actualizado para Python 2.7.9. Ver PEP 466 para justificación. https://www.python.org/downloads/release/python-279/. Esto habilita la compatibilidad con SNI en la biblioteca estándar para> v2.7.9

3: Inflexible: tal como se implementó, no hay forma de deshabilitar este comportamiento. La única opción para evitar el uso de requests del contexto pyopenssl es desinstalar pyopenssl para todo mi entorno de Python.

¿Fue útil esta página
0 / 5 - 0 calificaciones