python - ssl.SSLError: Version des tlsv1-Warnprotokolls




https cisco (5)

Ab Juli 2018 erfordert Pypi nun, dass Clients, die eine Verbindung herstellen, TLS 1.2 verwenden. Dies ist ein Problem, wenn Sie die mit MacOS (2.7.10) gelieferte Version von Python verwenden, da sie nur TLS 1.0 unterstützt. Sie können die Version von ssl ändern, mit der Python das Problem behebt, oder auf eine neuere Version von Python aktualisieren. Verwenden Sie Homebrew, um die neue Version von Python außerhalb des Standardverzeichnisses der Bibliothek zu installieren.

brew install [email protected]

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 für Informationen sendet. Der Code lautet wie folgt und entspricht dem in der Datei, außer 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.


Das Einzige, was Sie tun müssen, ist, requests[security] in Ihrem virtuellen Computer 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 auch nicht homebrew , um OpenSSL separat zu 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 es Anfragen, bei der Aushandlung der Verbindung die neueste Version von TLS zu verwenden. Das in macOS integrierte openssl unterstützt TLS v1.2.

Stellen Sie folgende Frage, bevor Sie Ihre eigene Version von OpenSSL installieren: Wie wird https://github.com von Google Chrome geladen ?


Ich glaube, TLSV1_ALERT_PROTOCOL_VERSION Sie, dass der Server TLS v1.0 nicht mit Ihnen TLSV1_ALERT_PROTOCOL_VERSION 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+ vielleicht?) Und möglicherweise OpenSSL benötigen (ich habe "OpenSSL 1.0.2k 26 Jan 2017" und die oben genannten scheinen zu funktionieren, YMMV).


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

  • Schritt 1: Brauen Sie Restall Python. jetzt hast du python3.7 anstatt des alten pythons

  • 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 von diesem Problem nicht gestört.


Keine der akzeptierten Antworten wies mich in die richtige Richtung, und dies ist immer noch die Frage, die bei der Suche nach dem Thema auftaucht. Hier ist also meine (teilweise) erfolgreiche Saga.

Hintergrund: Ich führe ein Python-Skript auf einem Beaglebone Black aus, das den Kryptowährungsaustausch Poloniex mithilfe der python-poloniex Bibliothek python-poloniex . Es hat plötzlich aufgehört, mit dem Fehler TLSV1_ALERT_PROTOCOL_VERSION zu arbeiten.

Es stellte sich heraus, dass OpenSSL in Ordnung war und der Versuch, eine v1.2-Verbindung zu erzwingen, eine gewaltige Verfolgungsjagd war - die Bibliothek wird nach 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.

Unterdessen hält die Version von Debian auf dem Beaglebone Python 3.3 für die neueste. Die Problemumgehung, die ich verwendet habe, war die Installation von Python 3.5 aus dem Quellcode (3.4 hat möglicherweise auch funktioniert, aber nach stundenlangem Ausprobieren 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 erspart eine Reihe von Neuversuchen. Die altinstall Installation verhindert, dass die Installation vorhandene Python-Binärdateien python3.5 stattdessen als python3.5 installiert. python3.5 , dass Sie zusätzliche Bibliotheken erneut installieren müssen. Die ./configure dauerte gut fünf oder zehn Minuten. Die make dauerte ein paar Stunden.

Nun funktionierte das immer noch nicht, bis ich endlich rannte

sudo -H pip3.5 install requests[security]

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

Wenn Sie also in Python den Fehler TLSV1_ALERT_PROTOCOL_VERSION erhalten, liegt dies wahrscheinlich daran, dass Sie TLS v1.2 nicht unterstützen können. Um Unterstützung 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 stattdessen mit SSL23_GET_SERVER_HELLO kämpfen.

Es stellte sich heraus, dass dies auf die ursprüngliche Ausgabe von Python zurückgeht, in der die falsche SSL-Version ausgewählt wurde. Dies kann mit this Trick bestätigt werden, indem eine Anforderungssitzung mit ssl_version=ssl.PROTOCOL_TLSv1_2 . Ohne 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 Anfrage tief in einer Bibliothek eines Drittanbieters eingeht. Sowohl diese Methode als auch diese Methode hätten den Trick machen sollen, aber keiner machte einen 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.





cisco