39 votes

ssl.SSLError: version du protocole d'alerte tlsv1

Je suis à l'aide de l'API REST pour un Cisco CMX appareil, et en essayant d'écrire du code Python qui fait une requête à l'API pour plus d'informations. Le code est comme suit et il est le même que dans le fichier, sauf avec les informations nécessaires changé.

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()

Cependant, je suis en permanence faire l'erreur suivante:

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)

J'ai aussi essayé la mise à jour d'OpenSSL, mais qui n'avait aucun effet.

67voto

J0ANMM Points 2047

J'ai eu le même message d'erreur et google m'a amené à cette question, voici donc ce que j'ai fait, en espérant que cela aide les autres dans une situation similaire.

Ceci est applicable pour OS X.

Vérifiez dans le Terminal de la version de OpenSSL j'ai eu:

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

Comme ma version de OpenSSL était trop vieux, l'on a accepté la réponse n'a pas de travail.

J'ai donc dû mettre à jour OpenSSL. Pour ce faire, j'ai mis à jour Python à la version la plus récente (à partir de la version 3.5 à partir de la version 3.6) avec Homebrew, à la suite de certaines des mesures suggérées ici:

$ brew update
$ brew install openssl
$ brew install python3

Puis j'ai eu des problèmes avec le CHEMIN d'accès et la version de python utilisée, donc je viens de créer un nouveau virtualenv veillant à ce que la dernière version de python a été prise:

$ virtualenv webapp --python=python3.6

Problème résolu.

36voto

Jim Lim Points 4981

La seule chose que vous avez à faire est d'installer l' requests[security] dans votre virtualenv. Vous ne devriez pas avoir à utiliser Python 3 (il faut travailler dans Python 2.7). En outre, si vous utilisez une version récente de mac os, vous n'avez pas à utiliser homebrew d'installer séparément OpenSSL soit.

$ 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] permet à des demandes d'utilisation de la dernière version de TLS lors de la négociation de la connexion. Le haut-openssl sur macOS prend en charge TLS v1.2.

Avant d'installer votre propre version de OpenSSL, poser cette question: comment est Google Chrome chargement https://github.com?

13voto

Josh Kupershmidt Points 1185

Je crois que TLSV1_ALERT_PROTOCOL_VERSION vous avertit que le serveur ne veut pas vous parler de TLS v1.0. Essayez de spécifier TLS v1.2 uniquement en respectant ces lignes:

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

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

Remarque, vous devrez peut-être suffisamment de nouvelles versions de Python (2.7.9+ peut-être?) Et peut-être d'OpenSSL (j'ai "OpenSSL 1.0.2k 26 janvier 2017" et ce qui précède semble fonctionner, YMMV)

9voto

Heath Raftery Points 1127

Aucune des réponses acceptées m'a orienté dans la bonne direction, et c'est toujours la question qui est soulevée lors de la recherche du sujet, donc voici mon (partiellement) le succès de la saga.

Contexte: j'utilise un script Python sur un Beaglebone Black qui interroge le cryptocurrency échange Poloniex à l'aide de l' python-poloniex de la bibliothèque. Il a soudainement arrêté de travailler avec le TLSV1_ALERT_PROTOCOL_VERSION erreur.

S'avère que OpenSSL était très bien, et d'essayer de forcer une v1.2 connexion a été un énorme wild goose chase - la bibliothèque de l'utilisation de la dernière version que nécessaire. Le maillon faible de la chaîne a été fait en Python, qui ne définit ssl.PROTOCOL_TLSv1_2, et donc commencé à prendre en charge TLS v1.2, depuis la version 3.4.

Pendant ce temps, la version de Debian sur le Beaglebone estime de Python 3.3, la dernière. La solution de contournement que j'ai utilisé était d'installer Python 3.5 à partir des sources (3.4 pourrait avoir finalement travaillé trop, mais après des heures d'essais et d'erreurs, je suis en fait):

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

Peut-être pas tous les paquets qui sont strictement nécessaires, mais l'installation de tous à la fois enregistre un tas de tentatives. L' altinstall empêche de l'installer à partir de casser existant python binaires, installation en tant que python3.5 au lieu de cela, bien que cela ne signifie pas que vous avez à ré-installer d'autres bibliothèques. L' ./configure a fallu un bon cinq ou dix minutes. L' make a pris deux heures.

Maintenant, cela ne fonctionne toujours pas jusqu'à ce que j'ai finalement couru

sudo -H pip3.5 install requests[security]

Qui installe également pyOpenSSL, cryptography et idna. Je soupçonne pyOpenSSL a la clé, donc peut - pip3.5 install -U pyopenssl aurait été suffisant, mais j'ai passé beaucoup trop de temps sur ce déjà pour s'en assurer.

Donc en résumé, si vous obtenez TLSV1_ALERT_PROTOCOL_VERSION erreur en Python, c'est probablement parce que vous ne pouvez pas en charge TLS v1.2. Pour ajouter le support, vous avez besoin d'au moins les éléments suivants:

  • OpenSSL 1.0.1
  • Python 3.4
  • les demandes[de sécurité]

Cela m'a fait passé TLSV1_ALERT_PROTOCOL_VERSION, et maintenant, je suis à la bataille avec SSL23_GET_SERVER_HELLO à la place.

S'avère que c'est retour à l'origine du Python en sélectionnant la mauvaise version de SSL. Cela peut être confirmé par l'utilisation de cette astuce pour le montage d'une demande de session avec ssl_version=ssl.PROTOCOL_TLSv1_2. Sans elle, SSLv23 est utilisé, et le SSL23_GET_SERVER_HELLO d'erreur s'affiche. Avec elle, la demande réussit.

La bataille finale a été à la force TLSv1_2 d'être repris lorsque la demande est faite au fond d'une bibliothèque tierce. Les deux cette méthode , et cette méthode devrait avoir fait le tour, mais ne fait aucune différence. Ma dernière solution est horrible, mais efficace. J'ai édité /usr/local/lib/python3.5/site-packages/urllib3/util/ssl_.py et changé

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

pour

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

et voila, mon script peut enfin communiquer avec le serveur à nouveau.

6voto

HommeDeJava Points 46

Pour Mac OS X

1) mise à Jour de Python 3.6.5 à l'aide de l'application native de l'installateur téléchargé à partir du site en langue officiel de Python https://www.python.org/downloads/

J'ai trouvé que le programme d'installation est en prenant soin de mettre à jour les liens et les liens symboliques pour le Python beaucoup mieux que homebrew.

2) Installer un nouveau certificat à l'aide de "./Installer Des Certificats.commande" qui est dans le actualisé Python 3.6 répertoire

> cd "/Applications/Python 3.6/"
> sudo "./Install Certificates.command"

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X