web-dev-qa-db-fra.com

Requêtes Python requests.exceptions.SSLError: [Errno 8] _ssl.c: 504: EOF s'est produite en violation du protocole

Je suis sur Ubuntu 12.10 avec OpenSSL 1.0.1c, python 2.7.3, Requests 1.0.3 et 1.0.4 (essayé les deux), et lors de la tentative de connexion au site Web dans la variable URL avec le code suivant .

def SendInitialRequest(xmlmessage, redirecturl):
    url = 'https://centineltest.cardinalcommerce.com/maps/txns.asp'

    payload = 'cmpi_msg=' + ET.tostring(xmlmessage)
    headers = {
        'Content-Type': 'application/x-www-form-urlencoded',
    }
    r = requests.post(url, data=payload, headers=headers, verify=None)
    print r.text

Il lève l'erreur suivante:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "clams/libs/centinel/thinclient.py", line 134, in SendInitialRequest
    r = requests.post(url, data=payload, headers=headers, verify=None)
  File "/home/jasonamyers/.virtualenv/clams/lib/python2.7/site-packages/requests/api.py", line 87, in post
    return request('post', url, data=data, **kwargs)
  File "/home/jasonamyers/.virtualenv/clams/lib/python2.7/site-packages/requests/api.py", line 44, in request
    return session.request(method=method, url=url, **kwargs)
  File "/home/jasonamyers/.virtualenv/clams/lib/python2.7/site-packages/requests/sessions.py", line 269, in request
    resp = self.send(prep, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies)
  File "/home/jasonamyers/.virtualenv/clams/lib/python2.7/site-packages/requests/sessions.py", line 364, in send
    r = adapter.send(request, **kwargs)
  File "/home/jasonamyers/.virtualenv/clams/lib/python2.7/site-packages/requests/adapters.py", line 163, in send
    raise SSLError(e)
requests.exceptions.SSLError: [Errno 8] _ssl.c:504: EOF occurred in violation of protocol

La tentative de connexion avec openssl renvoie les éléments suivants:

$ openssl s_client -connect centineltest.cardinalcommerce.com:443
CONNECTED(00000003)
140019346777760:error:140790E5:SSL routines:SSL23_WRITE:ssl handshake failure:s23_lib.c:177:
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 0 bytes and written 226 bytes
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
---

Si je le force à utiliser tls1 cela fonctionne (sortie tronquée):

$ openssl s_client -tls1 -connect centineltest.cardinalcommerce.com:443
CONNECTED(00000003)
depth=2 C = US, O = "thawte, Inc.", OU = Certification Services Division, OU
verify error:num=20:unable to get local issuer certificate
verify return:0
---

J'ai vu de nombreux rapports de bugs pour cela; Cependant, je n'ai pas trouvé le moyen de le contourner à l'aide de la bibliothèque de requêtes Python. Toute assistance sera grandement appréciée.

60
jasonamyers

Republiez ceci ici pour les autres depuis la page des demandes :

Requests 'ne prend pas en charge cette opération avant la version 1. Après la version 1, vous devez sous-classer HTTPAdapter, comme suit:

from requests.adapters import HTTPAdapter
from requests.packages.urllib3.poolmanager import PoolManager
import ssl

class MyAdapter(HTTPAdapter):
    def init_poolmanager(self, connections, maxsize, block=False):
        self.poolmanager = PoolManager(num_pools=connections,
                                       maxsize=maxsize,
                                       block=block,
                                       ssl_version=ssl.PROTOCOL_TLSv1)

Lorsque vous avez fait cela, vous pouvez faire ceci:

import requests
s = requests.Session()
s.mount('https://', MyAdapter())

Toute demande via cet objet de session utilisera alors TLSv1.

43
jasonamyers

La définition de verify = False ignore uniquement la vérification du certificat de serveur, mais ne permet pas de résoudre les erreurs de protocole SSL.

Ce problème est probablement dû à la désactivation de SSLv2 sur le serveur Web, mais Python 2.x tente d'établir une connexion avec PROTOCOL_SSLv23 par défaut. Cela se produit sur https://github.com/python/cpython/blob/360aa60b2a36f5f6e9e20325efd8d472f7559b1e/Lib/ssl.py#L1057

Vous pouvez corriger ssl.wrap_socket () dans le module ssl en remplaçant le paramètre mot-clé ssl_version. Le code suivant peut être utilisé tel quel. Mettez ceci au début de votre programme avant de faire des demandes. 

import ssl
from functools import wraps
def sslwrap(func):
    @wraps(func)
    def bar(*args, **kw):
        kw['ssl_version'] = ssl.PROTOCOL_TLSv1
        return func(*args, **kw)
    return bar

ssl.wrap_socket = sslwrap(ssl.wrap_socket)
36
chnrxn

L'installation des extras de paquets "sécurité" pour requests résolus pour moi:

Sudo apt-get installez libffi-dev

Sudo pip install -U demandes [sécurité]

24
Ricardo Cabral

C'est un bug connu, vous pouvez le contourner avec un hack:

Ouvrez site-packages/requests/packages/urllib3/connectionpool.py (ou faites simplement une copie locale des demandes dans votre propre projet) et modifiez le bloc qui dit:

def connect(self):
    # Add certificate verification
    sock = socket.create_connection((self.Host, self.port), self.timeout)

    # Wrap socket using verification with the root certs in
    # trusted_root_certs
    self.sock = ssl_wrap_socket(sock, self.key_file, self.cert_file,
                                cert_reqs=self.cert_reqs,
                                ca_certs=self.ca_certs,
                                server_hostname=self.Host,
                                ssl_version=self.ssl_version)

à:

def connect(self):
    # Add certificate verification
    sock = socket.create_connection((self.Host, self.port), self.timeout)

    # Wrap socket using verification with the root certs in
    # trusted_root_certs
    self.sock = ssl_wrap_socket(sock, self.key_file, self.cert_file,
                                cert_reqs=self.cert_reqs,
                                ca_certs=self.ca_certs,
                                server_hostname=self.Host,
                                ssl_version=ssl.PROTOCOL_TLSv1)

Sinon, je suppose qu’il existe une dérogation moins efficace, mais je n’en trouve pas une en quelques regards.

NOTE: Sur une note, requests à partir de PIP (1.0.4) sur un MacOS fonctionne uniquement avec l'URL fournie.

5
favoretti

Pour les personnes qui ne peuvent pas obtenir les correctifs ci-dessus fonctionnent.

Il a fallu changer le fichier ssl.py pour le réparer . Recherchez la fonction create_default_context et changez la ligne:

context = SSLContext(PROTOCOL_SSLv23)

à

context = SSLContext(PROTOCOL_TLSv1)

Peut-être que quelqu'un peut créer une solution plus facile sans modifier ssl.py?

3
Zhack

J'ai rencontré cette erreur et le correctif semble désactiver SNI, ce que Python 2.7 ne supporte pas:

http://bugs.python.org/issue5639

Erreur urllib3 sur python 2.7 SNI sur Google App Engine

3
Chris Pushbullet

J'ai eu le même problème:

soulève SSLError (e)
requests.exceptions.SSLError: [Errno 8] _ssl.c: 504: EOF s'est produit en violation du protocole.

J'avais un violon en cours d'exécution, j'ai arrêté la capture du violoneux et je n'ai pas vu cette erreur. Peut-être à cause de violoneux.

2
fd98279

J'ai eu cette erreur lors de la connexion à un serveur RabbitMQ MQTT via TLS. Je suis presque sûr que le serveur est en panne, mais de toute façon cela a fonctionné avec OpenSSL 1.0.1, mais pas OpenSSL 1.0.2.

Vous pouvez vérifier votre version en Python en utilisant ceci:

import ssl
ssl.OPENSSL_VERSION

Je ne suis pas sûr de savoir comment rétrograder OpenSSL dans Python (il semble être lié statiquement au moins sous Windows), à l'exception d'une version plus ancienne de Python.

0
Timmmm

Malheureusement, la réponse acceptée n'a pas fonctionné pour moi. Comme solution temporaire, vous pouvez également utiliser verify=False lors de la connexion au site Web sécurisé.

De Requêtes Python émettant SSLError

requests.get('https://example.com', verify=True)
0
bibstha

J'avais un problème similaire et je pense que si nous ignorons simplement la vérification ssl fonctionnera comme un charme, comme cela a fonctionné pour moi. Donc, vous connecter au serveur avec https, mais en leur demandant de ne pas vérifier le certificat.

Utilisation de requests. Il suffit de mentionner verify=False au lieu de None

    requests.post(url, data=payload, headers=headers, verify=False)

En espérant que cela fonctionnera pour ceux qui en ont besoin :).

0
MaNKuR