it-swarm.com.de

ssl.SSLError: tlsv1-Alertprotokollversion

Ich verwende die REST - API für ein Cisco CMX-Gerät und versuche, Python-Code zu schreiben, der eine GET-Anforderung an die API anfordert. Der Code lautet wie folgt und ist derselbe wie der in der Datei, mit der Ausnahme, dass die erforderlichen Informationen geändert wurden.

from http.client import HTTPSConnection
from base64 import b64encode


# Create HTTPS connection
c = HTTPSConnection("0.0.0.0")

# encode as Base64
# decode to ascii (python3 stores as byte string, need to pass as ascii 
value for auth)
username_password = b64encode(b"admin:password").decode("ascii")
headers = {'Authorization': 'Basic {0}'.format(username_password)}

# connect and ask for resource
c.request('GET', '/api/config/v1/aaa/users', headers=headers)

# response
res = c.getresponse()

data = res.read()

Ich erhalte jedoch ständig den folgenden Fehler: 

Traceback (most recent call last):
  File "/Users/finaris/PycharmProjects/test/test/test.py", line 14, in <module>
    c.request('GET', '/api/config/v1/aaa/users', headers=headers)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/http/client.py", line 1106, in request
    self._send_request(method, url, body, headers)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/http/client.py", line 1151, in _send_request
    self.endheaders(body)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/http/client.py", line 1102, in endheaders
    self._send_output(message_body)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/http/client.py", line 934, in _send_output
    self.send(msg)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/http/client.py", line 877, in send
    self.connect()
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/http/client.py", line 1260, in connect
    server_hostname=server_hostname)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/ssl.py", line 377, in wrap_socket
    _context=self)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/ssl.py", line 752, in __init__
    self.do_handshake()
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/ssl.py", line 988, in do_handshake
    self._sslobj.do_handshake()
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/ssl.py", line 633, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLError: [SSL: TLSV1_ALERT_PROTOCOL_VERSION] tlsv1 alert protocol version (_ssl.c:645)

Ich habe auch versucht, OpenSSL zu aktualisieren, aber das hatte keine Auswirkungen.

25
finaris

Ich hatte den gleichen Fehler und Google brachte mich zu dieser Frage. Ich habe also das getan, was ich getan habe, in der Hoffnung, dass es anderen in einer ähnlichen Situation hilft.

Dies gilt für OS X.

Überprüfen Sie im Terminal, welche Version von OpenSSL ich hatte:

$ python3 -c "import ssl; print(ssl.OPENSSL_VERSION)"
>> OpenSSL 0.9.8zh 14 Jan 2016

Da meine Version von OpenSSL zu alt war, funktionierte die akzeptierte Antwort nicht.

Also musste ich OpenSSL aktualisieren. Um dies zu erreichen, habe ich Python mit Homebrew auf die neueste Version (von Version 3.5 auf Version 3.6) aktualisiert. Dabei habe ich einige der vorgeschlagenen Schritte hier ausgeführt:

$ brew update
$ brew install openssl
$ brew install python3

Dann hatte ich Probleme mit dem PATH und der verwendeten Python-Version. Deshalb habe ich gerade eine neue virtualenv erstellt, um sicherzustellen, dass die neueste Version von Python verwendet wurde:

$ virtualenv webapp --python=python3.6

Problem gelöst.

46
J0ANMM

Das einzige, was Sie tun müssen, ist, requests[security] in Ihrer virtualenv zu installieren. Sie sollten Python 3 nicht verwenden müssen (es sollte in Python 2.7 funktionieren). Wenn Sie eine neuere Version von macOS verwenden, müssen Sie OpenSSL auch nicht mit homebrew separat installieren.

$ virtualenv --python=/usr/bin/python tempenv  # uses system python
$ . tempenv/bin/activate
$ pip install requests
$ python
>>> import ssl
>>> ssl.OPENSSL_VERSION
'OpenSSL 0.9.8zh 14 Jan 2016'  # this is the built-in openssl
>>> import requests
>>> requests.get('https://api.github.com/users/octocat/orgs')
requests.exceptions.SSLError: HTTPSConnectionPool(Host='api.github.com', port=443): Max retries exceeded with url: /users/octocat/orgs (Caused by SSLError(SSLError(1, u'[SSL: TLSV1_ALERT_PROTOCOL_VERSION] tlsv1 alert protocol version (_ssl.c:590)'),))
$ pip install 'requests[security]'
$ python  # install requests[security] and try again
>>> import requests
>>> requests.get('https://api.github.com/users/octocat/orgs')
<Response [200]>

requests[security] ermöglicht bei Anfragen die Verwendung der neuesten TLS-Version, wenn die Verbindung ausgehandelt wird. Das in macOS integrierte openssl unterstützt TLS v1.2.

Stellen Sie vor der Installation Ihrer eigenen Version von OpenSSL folgende Frage: Wie lädt Google Chrome https://github.com ?

18
James Lim

Keine der akzeptierten Antworten hat mich in die richtige Richtung gelenkt, und dies ist immer noch die Frage, die bei der Suche des Themas auftaucht. Hier ist meine (teilweise) erfolgreiche Saga.

Hintergrund: Ich führe ein Python-Skript auf einem Beaglebone Black aus, das den Kryptowährungsaustausch Poloniex mit der Bibliothek python-poloniex abfragt. Es wurde plötzlich nicht mehr mit dem Fehler TLSV1_ALERT_PROTOCOL_VERSION gearbeitet.

Es stellte sich heraus, dass OpenSSL in Ordnung war, und der Versuch, eine v1.2-Verbindung zu erzwingen, war eine wilde Verfolgungsjagd - die Bibliothek wird bei Bedarf die neueste Version verwenden. Das schwache Glied in der Kette war eigentlich Python, das nur ssl.PROTOCOL_TLSv1_2 definierte und daher seit Version 3.4 TLS v1.2 unterstützte.

Inzwischen hält die Version von Debian auf dem Beaglebone Python 3.3 für den neuesten Stand. Die verwendete Problemumgehung bestand darin, Python 3.5 aus dem Quellcode zu installieren (3.4 hat möglicherweise auch funktioniert, aber nach stundenlangen Versuchen und Versuchen bin ich fertig):

Sudo apt-get install build-essential checkinstall
Sudo apt-get install libreadline-gplv2-dev libncursesw5-dev libssl-dev libsqlite3-dev tk-dev libgdbm-dev libc6-dev libbz2-dev
wget https://www.python.org/ftp/python/3.5.4/Python-3.5.4.tgz
Sudo tar xzf Python-3.5.4.tgz
cd Python-3.5.4
./configure
Sudo make altinstall

Möglicherweise sind nicht alle diese Pakete unbedingt erforderlich, aber die gleichzeitige Installation spart eine Reihe von Wiederholungen. Die altinstall verhindert, dass die Installation vorhandene Python-Binärdateien blockiert. Stattdessen wird python3.5 installiert. Dies bedeutet jedoch, dass Sie zusätzliche Bibliotheken neu installieren müssen. Der ./configure dauerte gut fünf oder zehn Minuten. Die make dauerte ein paar Stunden.

Jetzt funktionierte das immer noch nicht, bis ich endlich lief

Sudo -H pip3.5 install requests[security]

Damit werden auch pyOpenSSL, cryptography und idna installiert. Ich vermute, pyOpenSSL war der Schlüssel. Vielleicht wäre pip3.5 install -U pyopenssl ausreichend gewesen, aber ich habe schon viel zu lange damit verbracht, um sicher zu gehen.

Zusammenfassend gesagt: Wenn Sie den Fehler TLSV1_ALERT_PROTOCOL_VERSION in Python erhalten, liegt dies wahrscheinlich daran, dass Sie TLS v1.2 nicht unterstützen können. Um Support hinzuzufügen, benötigen Sie mindestens Folgendes:

  • OpenSSL 1.0.1
  • Python 3.4
  • anfragen [Sicherheit]

Das hat mich an TLSV1_ALERT_PROTOCOL_VERSION vorbei gebracht, und jetzt kann ich mich stattdessen mit SSL23_GET_SERVER_HELLO kämpfen.

Es stellt sich heraus, dass dies wieder die ursprüngliche Ausgabe von Python ist, die die falsche SSL-Version auswählt. Dies kann durch Verwendung eines this -Tricks bestätigt werden, um eine Anforderungssitzung mit ssl_version=ssl.PROTOCOL_TLSv1_2 bereitzustellen. Andernfalls wird SSLv23 verwendet und der Fehler SSL23_GET_SERVER_HELLO wird angezeigt. Damit ist die Anfrage erfolgreich.

Der letzte Kampf bestand darin, TLSv1_2 zu zwingen, ausgewählt zu werden, wenn die Anforderung tief in einer Drittbibliothek gestellt wird. Sowohl diese Methode als auch diese Methode hätten den Trick ausführen sollen, aber beide machten keinen Unterschied. Meine endgültige Lösung ist schrecklich, aber effektiv. Ich habe /usr/local/lib/python3.5/site-packages/urllib3/util/ssl_.py bearbeitet und geändert

def resolve_ssl_version(candidate):
    """
    like resolve_cert_reqs
    """
    if candidate is None:
        return PROTOCOL_SSLv23

    if isinstance(candidate, str):
        res = getattr(ssl, candidate, None)
        if res is None:
            res = getattr(ssl, 'PROTOCOL_' + candidate)
        return res

    return candidate

zu

def resolve_ssl_version(candidate):
    """
    like resolve_cert_reqs
    """
    if candidate is None:
        return ssl.PROTOCOL_TLSv1_2

    if isinstance(candidate, str):
        res = getattr(ssl, candidate, None)
        if res is None:
            res = getattr(ssl, 'PROTOCOL_' + candidate)
        return res

    return candidate

und voila, mein script kann endlich wieder den server kontaktieren.

8
Heath Raftery

Ich glaube, TLSV1_ALERT_PROTOCOL_VERSION weist Sie darauf hin, dass der Server TLS v1.0 nicht mit Ihnen sprechen möchte. Versuchen Sie, TLS v1.2 nur anzugeben, indem Sie die folgenden Zeilen einfügen:

import ssl
context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)

# Create HTTPS connection
c = HTTPSConnection("0.0.0.0", context=context)

Beachten Sie, dass Sie möglicherweise ausreichend neue Versionen von Python (2.7.9+ oder vielleicht?) Und möglicherweise OpenSSL benötigen (ich habe "OpenSSL 1.0.2k 26 Jan 2017" und das oben scheint zu funktionieren, YMMV).

6

Für Mac OS X

1) Update auf Python 3.6.5 mit dem nativen App-Installationsprogramm, das von der offiziellen Python-Website heruntergeladen wurde https://www.python.org/downloads/

Ich habe festgestellt, dass der Installer die Links und Symlinks für den neuen Python viel besser aktualisiert als Homebrew. 

2) Installieren Sie ein neues Zertifikat mit "./Install Certificates.command" im aktualisierten Python 3.6-Verzeichnis 

> cd "/Applications/Python 3.6/"
> Sudo "./Install Certificates.command"
3
Claude COULOMBE

Seit Juli 2018 verlangt Pypi nun, dass Clients, die eine Verbindung herstellen, TLS 1.2 verwenden. Dies ist ein Problem, wenn Sie die im Lieferumfang von MacOS (2.7.10) enthaltene Version von Python verwenden, da nur TLS 1.0 unterstützt wird. Sie können die Version von ssl ändern, die Python verwendet, um das Problem zu beheben, oder auf eine neuere Version von Python aktualisieren. Verwenden Sie Homebrew, um die neue Version von Python außerhalb des Standardspeicherorts der Bibliothek zu installieren. 

brew install [email protected]
2
BenJi

Ich habe auch dieses Problem ... In Macos ist hier die Lösung:

  • Schritt 1: Brühen Sie Restall-Python. Jetzt hast du Python3.7 anstelle des alten Python

  • Schritt 2: Erstellen Sie die neue Env-Basis auf Python3.7. Mein Pfad ist /usr/local/Cellar/python/3.7.2/bin/python3.7

jetzt werden Sie durch dieses Problem nicht gestört.

0
Maestro Pu