it-swarm.com.de

Python fordert request.exceptions.SSLError: [Errno 8] _ssl.c: 504: EOF ist protokollverletzt aufgetreten

Ich bin auf Ubuntu 12.10 mit OpenSSL 1.0.1c, Python 2.7.3, Requests 1.0.3 und 1.0.4 (versucht beide) und beim Versuch, eine Verbindung zur Website in der URL-Variablen mit dem folgenden Code herzustellen .

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

Es wird der folgende Fehler ausgegeben:

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

Beim Versuch der Verbindung mit openssl wird Folgendes zurückgegeben:

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

Wenn ich es erzwinge, tls1 zu verwenden, funktioniert es (die Ausgabe wird abgeschnitten):

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

Ich habe zahlreiche Fehlerberichte dafür gesehen; Ich habe jedoch keine Möglichkeit gefunden, mit der Python-Anforderungsbibliothek umzugehen. Jede Hilfe wäre sehr dankbar.

60
jasonamyers

Stellen Sie dies hier für andere von der Seite "Anfragen" wieder her:

Requests 'unterstützt dies nicht vor Version 1. Nach Version 1 wird erwartet, dass Sie den HTTPAdapter wie folgt subclassieren:

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)

Wenn Sie das getan haben, können Sie Folgendes tun:

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

Jede Anforderung über dieses Sitzungsobjekt verwendet dann TLSv1.

43
jasonamyers

Wenn Sie verifizieren = False festlegen, wird nur die Überprüfung des Serverzertifikats übersprungen, dies hilft jedoch nicht, SSL-Protokollfehler zu beheben.

Dieses Problem ist wahrscheinlich darauf zurückzuführen, dass SSLv2 auf dem Webserver deaktiviert ist, aber Python 2.x versucht, standardmäßig eine Verbindung mit PROTOCOL_SSLv23 herzustellen. Dies geschieht unter https://github.com/python/cpython/blob/360aa60b2a36f5f6e9e20325efd8d472f7559b1e/Lib/ssl.py#L1057

Sie können den ssl.wrap_socket () im ssl-Modul mit einem Patch versehen, indem Sie den Schlüsselparameter ssl_version überschreiben. Der folgende Code kann unverändert verwendet werden. Setzen Sie dies an den Anfang Ihres Programms, bevor Sie eine Anfrage stellen. 

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

Die Installation der "Sicherheit" -Paket-Extras für requests wurde für mich gelöst:

Sudo apt-get install libffi-dev

Sudo pip install -U fordert [Sicherheit] an

24
Ricardo Cabral

Dies ist ein bekannter Fehler, den Sie mit einem Hack umgehen können:

Öffnen Sie site-packages/requests/packages/urllib3/connectionpool.py (oder erstellen Sie einfach eine lokale Kopie der Anforderungen in Ihrem eigenen Projekt) und ändern Sie den Block mit folgendem Wortlaut:

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)

zu:

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)

Andernfalls gibt es irgendwo einen Override, der weniger abgehackt ist, aber ich konnte mit ein paar Blicken keinen finden.

NOTE: Bei einer Randnotiz arbeitet requests aus PIP (1.0.4) unter Mac OS nur mit der von Ihnen angegebenen URL.

5
favoretti

Für Leute, die nicht über Fixes arbeiten können.

Musste die Datei ssl.py ändern, um das Problem zu beheben. Suchen Sie nach der Funktion create_default_context und ändern Sie die Zeile:

context = SSLContext(PROTOCOL_SSLv23)

zu

context = SSLContext(PROTOCOL_TLSv1)

Vielleicht kann jemand eine leichtere Lösung erstellen, ohne ssl.py zu bearbeiten?

3
Zhack

Ich bin auf diesen Fehler gestoßen und der Fix scheint SNI zu deaktivieren, was Python 2.7 nicht unterstützt:

http://bugs.python.org/issue5639

urllib3 auf Python 2.7 SNI-Fehler in Google App Engine

3

Ich hatte das gleiche Problem:

sSLError erhöhen (e)
request.exceptions.SSLError: [Errno 8] _ssl.c: 504: EOF trat unter Verletzung des Protokolls auf

Ich hatte Fiddler ausgeführt, ich habe die Fiddler-Capture eingestellt und habe diesen Fehler nicht gesehen. Könnte wegen Geiger sein.

2
fd98279

Dieser Fehler ist aufgetreten, als ich mich über TLS mit einem RabbitMQ MQTT-Server verbunden habe. Ich bin mir ziemlich sicher, dass der Server defekt ist, aber es hat trotzdem mit OpenSSL 1.0.1 funktioniert, aber nicht OpenSSL 1.0.2.

Sie können Ihre Version in Python folgendermaßen überprüfen:

import ssl
ssl.OPENSSL_VERSION

Ich bin mir nicht sicher, wie ich OpenSSL in Python downgraden soll (es scheint zumindest unter Windows statisch zu sein), mit Ausnahme einer älteren Python-Version.

0
Timmmm

Leider hat die akzeptierte Antwort für mich nicht funktioniert. Als temporäre Problemumgehung können Sie auch verify=False verwenden, wenn Sie eine Verbindung zur sicheren Website herstellen.

Von Python-Anfragen werfen SSLError auf

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

Ich hatte ein ähnliches Problem und ich denke, wenn wir einfach ignorieren, dass die ssl-Überprüfung wie Charme funktioniert, wie es für mich funktioniert. Verbinden Sie sich also mit dem https-Schema mit dem Server, weisen Sie ihn jedoch an, das Zertifikat nicht zu überprüfen.

requests verwenden. Erwähnen Sie einfach verify=False anstelle von None

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

Ich hoffe, das funktioniert für diejenigen, die es brauchen :).

0
MaNKuR