SSLError: mal saludo, peticiones Python

Estoy consumiendo las API de Ebay Trading usando Ebay python sdk, que a la larga se traduce en solicitudes de python para realizar llamadas a la API.

Todo funcionaba bien, pero desde los últimos días no puedo hacer llamadas. Estoy recibiendo error:

SSLError: bad handshake: Error([('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE', 'certificate verify failed')],) 

Aquí está el rastreo completo:

 In [9]: response = api.execute('GetSessionID', data) --------------------------------------------------------------------------- SSLError Traceback (most recent call last)  in () ----> 1 response = api.execute('GetSessionID', data) /home/debian/.virtualenvs/myvirtualenv/local/lib/python2.7/site-packages/ebaysdk/connection.pyc in execute(self, verb, data, list_nodes, verb_attrs, files) 117 118 self.build_request(verb, data, verb_attrs, files) --> 119 self.execute_request() 120 121 if hasattr(self.response, 'content'): /home/debian/.virtualenvs/goplaces/local/lib/python2.7/site-packages/ebaysdk/connection.pyc in execute_request(self) 182 proxies=self.proxies, 183 timeout=self.timeout, --> 184 allow_redirects=True 185 ) 186 /home/debian/.virtualenvs/myvirtualenv/local/lib/python2.7/site-packages/requests/sessions.pyc in send(self, request, **kwargs) 574 575 # Send the request --> 576 r = adapter.send(request, **kwargs) 577 578 # Total elapsed time of the request (approximately) /home/debian/.virtualenvs/myvirtualenv/local/lib/python2.7/site-packages/requests/adapters.pyc in send(self, request, stream, timeout, verify, cert, proxies) 431 except (_SSLError, _HTTPError) as e: 432 if isinstance(e, _SSLError): --> 433 raise SSLError(e, request=request) 434 elif isinstance(e, ReadTimeoutError): 435 raise ReadTimeout(e, request=request) SSLError: bad handshake: Error([('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE', 'certificate verify failed')],) 

Hay muchas preguntas relacionadas sobre StackOverflow, todas las cuales dicen:

  1. pasar argumento verificar = falso
  2. pasar certificado de CA
  3. adjunte su certificado de CA en el archivo cacert.pem (probé esto, no funcionó)

No puedo hacer esto porque:

  1. Las solicitudes están siendo llamadas por una biblioteca de terceros que está en mi virtualenvirinent.
  2. Esto es malo en el punto de vista de seguridad.

También,

  1. Puedo hacer otras llamadas TSL (por ejemplo, apis de Amazon marketplace) en el mismo virtualenv usando solicitudes, que no causan un mal saludo o cualquier otro error de SSL.
  2. Ebay SDK funciona bien en mi sistema local (Mac OsX), el problema es solo con mi servidor de producción (Google Cloud / Debian)
  3. No hay errores SSL reportados por chrome en mi dominio

No sé por qué está sucediendo esto.

Por qué las SSL routines', 'SSL3_GET_SERVER_CERTIFICATE', 'certificate verify failed' está en traceback, cuando tengo deshabilitado SSL3. (No tengo un conocimiento profundo sobre SSL).

¡Gracias!

Editar:

 # openssl version OpenSSL 1.0.2e 3 Dec 2015 

Se actualizó a openssl 1.0.2 desde 1.0.1 construyendo desde la fuente después de la sugerencia de @Steffen Ullrich.

 $ pip freeze | grep -i ssl backports.ssl-match-hostname==3.4.0.2 pyOpenSSL==0.15.1 

Related of "SSLError: mal saludo, peticiones Python"

Supongo que esto está relacionado con el error de Python Urllib2 SSL , es decir, un problema de múltiples rutas de confianza en la implementación subyacente de OpenSSL. Vea allí para los detalles del problema.

Para solucionar este problema sin realizar cambios en sus CA de confianza, deberá tener un OpenSSL fijo, es decir, OpenSSL 1.0.2. O puede agregar algunos de los certificados de CA más antiguos a su almacén de confianza.

  1. pasar argumento verificar = falso
  2. pasar certificado de CA
  3. adjunte su certificado de CA en el archivo cacert.pem (probé esto, no funcionó)

… Esto es malo en el punto de vista de seguridad.

Si bien verify=False es malo para la seguridad porque deshabilita la validación, las otras opciones no son malas porque solo agregan anclas de confianza adicionales pero mantienen la validación habilitada.

Por qué las rutinas de SSL ‘,’ SSL3_GET_SERVER_CERTIFICATE ‘,’ certificado de verificación fallida ‘está en traceback, cuando tengo deshabilitado SSL3.

Incluso si se habla de SSLv3 no significa eso. TLS y SSLv3 comparten muchas funcionalidades, es decir, TLS 1.0 es en realidad SSL 3.1. Por lo tanto, muchas de las funciones SSL3_* en el código OpenSSL se usan con TLS 1.x también, lo que causa estos mensajes irritantes.

Creo que está relacionado con esta sección de https://pypi.python.org/pypi/certifi/

Certificados de raíz de 1024 bits

Los exploradores y las autoridades de certificación han llegado a la conclusión de que las claves de 1024 bits son inaceptablemente débiles para los certificados, especialmente los certificados raíz. Por esta razón, Mozilla ha eliminado cualquier certificado débil (es decir, clave de 1024 bits) de su paquete, reemplazándolo con un certificado equivalente (es decir, 2048 bits o mayor clave) de la misma CA. Como Mozilla eliminó estos certificados de su paquete, certifi los eliminó también.

Desafortunadamente, las versiones anteriores de OpenSSL (menos de 1.0.2) a veces no validan las cadenas de certificados que usan las raíces fuertes. Por este motivo, si no puede validar un certificado utilizando el mecanismo certifi.where (), puede volver a agregar intencionalmente las raíces de 1024 bits a su paquete llamando a certifi.old_where () en su lugar. Esto no se recomienda en producción: si es posible, debería actualizar a un OpenSSL más nuevo. Sin embargo, si no tiene otra opción, esto puede funcionar para usted.

Mi prueba es la siguiente:

 root@43b7ec35c240:/usr/src/app# cat /etc/debian_version 8.2 root@43b7ec35c240:/usr/src/app# cat test.py import logging import requests logging.basicConfig() logging.getLogger().setLevel(logging.DEBUG) requests_log = logging.getLogger("requests.packages.urllib3") requests_log.setLevel(logging.DEBUG) requests_log.propagate = True requests.get('https://www.google.com/') root@43b7ec35c240:/usr/src/app# python test.py INFO:requests.packages.urllib3.connectionpool:Starting new HTTPS connection (1): www.google.com DEBUG:requests.packages.urllib3.connectionpool:"GET / HTTP/1.1" 302 263 INFO:requests.packages.urllib3.connectionpool:Starting new HTTPS connection (1): www.google.com.hk DEBUG:requests.packages.urllib3.connectionpool:"GET /?gfe_rd=cr&ei=XXKbVqqBD8WM8Qe3v7-YAQ HTTP/1.1" 200 None root@43b7ec35c240:/usr/src/app# openssl version OpenSSL 1.0.1k 8 Jan 2015 root@43b7ec35c240:/usr/src/app# pip install certifi Collecting certifi Using cached certifi-2015.11.20.1-py2.py3-none-any.whl Installing collected packages: certifi Successfully installed certifi-2015.11.20.1 root@43b7ec35c240:/usr/src/app# python test.py INFO:requests.packages.urllib3.connectionpool:Starting new HTTPS connection (1): www.google.com Traceback (most recent call last): File "test.py", line 16, in  requests.get('https://www.google.com/') File "/usr/local/lib/python2.7/site-packages/requests/api.py", line 69, in get return request('get', url, params=params, **kwargs) File "/usr/local/lib/python2.7/site-packages/requests/api.py", line 50, in request response = session.request(method=method, url=url, **kwargs) File "/usr/local/lib/python2.7/site-packages/requests/sessions.py", line 468, in request resp = self.send(prep, **send_kwargs) File "/usr/local/lib/python2.7/site-packages/requests/sessions.py", line 576, in send r = adapter.send(request, **kwargs) File "/usr/local/lib/python2.7/site-packages/requests/adapters.py", line 433, in send raise SSLError(e, request=request) requests.exceptions.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:590) root@43b7ec35c240:/usr/src/app# pip uninstall certifi Uninstalling certifi-2015.11.20.1: /usr/local/lib/python2.7/site-packages/certifi-2015.11.20.1.dist-info/DESCRIPTION.rst /usr/local/lib/python2.7/site-packages/certifi-2015.11.20.1.dist-info/METADATA /usr/local/lib/python2.7/site-packages/certifi-2015.11.20.1.dist-info/RECORD /usr/local/lib/python2.7/site-packages/certifi-2015.11.20.1.dist-info/WHEEL /usr/local/lib/python2.7/site-packages/certifi-2015.11.20.1.dist-info/metadata.json /usr/local/lib/python2.7/site-packages/certifi-2015.11.20.1.dist-info/top_level.txt /usr/local/lib/python2.7/site-packages/certifi/__init__.py /usr/local/lib/python2.7/site-packages/certifi/__init__.pyc /usr/local/lib/python2.7/site-packages/certifi/__main__.py /usr/local/lib/python2.7/site-packages/certifi/__main__.pyc /usr/local/lib/python2.7/site-packages/certifi/cacert.pem /usr/local/lib/python2.7/site-packages/certifi/core.py /usr/local/lib/python2.7/site-packages/certifi/core.pyc /usr/local/lib/python2.7/site-packages/certifi/old_root.pem /usr/local/lib/python2.7/site-packages/certifi/weak.pem Proceed (y/n)? y Successfully uninstalled certifi-2015.11.20.1 root@43b7ec35c240:/usr/src/app# python test.py INFO:requests.packages.urllib3.connectionpool:Starting new HTTPS connection (1): www.google.com DEBUG:requests.packages.urllib3.connectionpool:"GET / HTTP/1.1" 302 263 INFO:requests.packages.urllib3.connectionpool:Starting new HTTPS connection (1): www.google.com.hk DEBUG:requests.packages.urllib3.connectionpool:"GET /?gfe_rd=cr&ei=AnObVtG4BcGM8QeC6r-YCw HTTP/1.1" 200 None 

Luego trato de actualizar mi paquete libssl haciendo:

 # curl http://apt.wikimedia.org/autoinstall/keyring/wikimedia-archive-keyring.gpg | apt-key add - # echo "deb http://apt.wikimedia.org/wikimedia jessie-wikimedia backports" >> /etc/apt/sources.list # apt-get update # apt-get install libssl1.0.0 # openssl version OpenSSL 1.0.1k 8 Jan 2015 (Library: OpenSSL 1.0.2e 3 Dec 2015) 

Después de eso, incluso con certifi instalado, estoy todo bien.

 # pip freeze |grep certifi certifi==2015.11.20.1 # python test.py INFO:requests.packages.urllib3.connectionpool:Starting new HTTPS connection (1): www.google.com DEBUG:requests.packages.urllib3.connectionpool:"GET / HTTP/1.1" 302 263 INFO:requests.packages.urllib3.connectionpool:Starting new HTTPS connection (1): www.google.com.hk DEBUG:requests.packages.urllib3.connectionpool:"GET /?gfe_rd=cr&ei=4XSbVt2gK8OM8Qe1tICIBA HTTP/1.1" 200 None