ssl.SSLError: tlsv1 alert protocol version
ssl.SSLError: tlsv1 alert protocol version
我将 REST API 用于 Cisco CMX device,并尝试编写 Python 代码以向 API 发出获取信息的 GET 请求。代码如下,除必要信息有所改动外,与文件中的相同。
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()
但是,我不断收到以下错误:
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)
我也尝试更新 OpenSSL,但没有效果。
我相信 TLSV1_ALERT_PROTOCOL_VERSION
提醒您服务器不想与您交谈 TLS v1.0。尝试仅通过坚持这些行来指定 TLS v1.2:
import ssl
from http.client import HTTPSConnection
context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
# Create HTTPS connection
c = HTTPSConnection("0.0.0.0", context=context)
请注意,您可能需要足够新的 Python 版本(也许是 2.7.9+?),可能还需要 OpenSSL(我有“OpenSSL 1.0.2k 26 Jan 2017”,以上版本似乎有效,YMMV )
我有同样的错误,google让我想到了这个问题,所以这就是我所做的,希望它能帮助处于类似情况的其他人。
这适用于 OS X。
在终端中检查我使用的是哪个版本的 OpenSSL:
$ python3 -c "import ssl; print(ssl.OPENSSL_VERSION)"
>> OpenSSL 0.9.8zh 14 Jan 2016
由于我的 OpenSSL 版本太旧,接受的答案无效。
所以我不得不更新 OpenSSL。为此,我按照建议的一些步骤 here:
使用 Homebrew 将 Python 更新到最新版本(从 3.5 版到 3.6 版)
$ brew update
$ brew install openssl
$ brew install python3
然后我遇到了 PATH 和正在使用的 python 版本的问题,所以我创建了一个新的 virtualenv
确保采用了最新版本的 python :
$ virtualenv webapp --python=python3.6
问题已解决。
None 的已接受答案为我指明了正确的方向,这仍然是搜索主题时出现的问题,所以这是我(部分)成功的传奇。
背景:我 运行 Beaglebone Black 上的 Python 脚本使用 python-poloniex 库轮询加密货币交易所 Poloniex。它突然停止工作并出现 TLSV1_ALERT_PROTOCOL_VERSION 错误。
事实证明 OpenSSL 没问题,而试图强制建立 v1.2 连接是一个巨大的徒劳的尝试 - 该库将根据需要使用最新版本。链中的弱 link 实际上是 Python,它只定义了 ssl.PROTOCOL_TLSv1_2
,因此从 3.4 版本开始支持 TLS v1.2。
同时,Beaglebone 上的 Debian 版本认为 Python 3.3 是最新的。我使用的解决方法是从源代码安装 Python 3.5(3.4 最终可能也能工作,但经过数小时的反复试验后我完成了):
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
也许并非所有这些软件包都是绝对必要的,但一次安装它们可以节省大量重试。 altinstall
防止安装破坏现有的 python 二进制文件,而是安装为 python3.5
,尽管这确实意味着您必须重新安装其他库。 ./configure
花了整整五到十分钟。 make
花了几个小时。
直到我终于运行
,这仍然没有用
sudo -H pip3.5 install requests[security]
它还会安装 pyOpenSSL
、cryptography
和 idna
。我怀疑 pyOpenSSL
是关键,所以也许 pip3.5 install -U pyopenssl
就足够了,但我已经花了太长时间来确定这一点。
总而言之,如果您在 Python 中遇到 TLSV1_ALERT_PROTOCOL_VERSION 错误,可能是因为您不支持 TLS v1.2。要添加支持,您至少需要以下内容:
- OpenSSL 1.0.1
- Python 3.4
- 请求[安全]
这让我过去了 TLSV1_ALERT_PROTOCOL_VERSION,现在我开始与 SSL23_GET_SERVER_HELLO 战斗。
原来这又回到了最初的问题 Python 选择了错误的 SSL 版本。这可以通过使用 this 技巧通过 ssl_version=ssl.PROTOCOL_TLSv1_2
安装请求会话来确认。没有它,将使用 SSLv23 并出现 SSL23_GET_SERVER_HELLO 错误。有了它,请求就成功了。
最后的战斗是在第三方库深处提出请求时强制选择 TLSv1_2。 this method and this method 都应该可以解决问题,但两者都没有任何区别。我的最终解决方案很糟糕,但很有效。我编辑了 /usr/local/lib/python3.5/site-packages/urllib3/util/ssl_.py
并更改了
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
至
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
瞧,我的脚本终于可以再次联系服务器了。
您唯一需要做的就是在您的 virtualenv 中安装 requests[security]
。您不必使用 Python 3(它应该在 Python 2.7 中工作)。此外,如果您使用的是最新版本的 macOS,您也不必使用 homebrew
单独安装 OpenSSL。
$ 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]
允许请求在协商连接时使用最新版本的 TLS。 built-in macOS 上的 openssl 支持 TLS v1.2。
Before you install your own version of OpenSSL, ask this question: how is Google Chrome loading https://github.com?
对于Mac OS X
1) 使用从官方 Python 语言网站下载的本机应用程序安装程序更新到 Python 3.6.5 https://www.python.org/downloads/
我发现安装程序正在为新 Python 更新链接和符号链接,这比自制软件要好得多。
2) 使用刷新后的 Python 3.6 目录
中的“./Install Certificates.command”安装新证书
> cd "/Applications/Python 3.6/"
> sudo "./Install Certificates.command"
自 2018 年 7 月起,Pypi 现在要求连接到它的客户端使用 TLS 1.2。如果您使用的是 MacOS (2.7.10) 附带的 python 版本,这是一个问题,因为它仅支持 TLS 1.0。您可以更改 python 正在使用的 ssl 版本来解决问题或升级到更新版本的 python。使用 homebrew 在默认库位置之外安装 python 的新版本。
brew install python@2
我也遇到了这个问题。
在 macos 中,这里是解决方案:
第 1 步:brew restall python。现在你得到了 python3.7 而不是旧的 python
第 2 步:基于 python3.7 构建新环境。我的路径是 /usr/local/Cellar/python/3.7.2/bin/python3.7
现在,你不会被这个问题打扰了。
我在尝试 gem install bundler
时遇到了这个问题,我对所有 Python 的响应感到困惑(因为我使用的是 Ruby)。这是我的确切错误:
ERROR: Could not find a valid gem 'bundler' (>= 0), here is why:
Unable to download data from https://rubygems.org/ - SSL_connect returned=1 errno=0 state=SSLv2/v3 read server hello A: tlsv1 alert protocol version (https://rubygems.org/latest_specs.4.8.gz)
我的解决方案:我将 Ruby 更新到最新版本 (2.6.5)。问题已解决。
此问题的另一个来源:我发现在 Debian 9 中,Python httplib2 被硬编码为坚持使用 TLS v1.0。因此,任何使用 httplib2 连接到坚持更高安全性的服务器的应用程序都会失败,并显示 TLSV1_ALERT_PROTOCOL_VERSION.
我通过更改
修复了它
context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
至
context = ssl.SSLContext()
在 /usr/lib/python3/dist-packages/httplib2/__init__.py .
Debian 10 没有这个问题。
对于 python2 用户 MacOS (python@2 公式将获胜'找不到),因为 brew 停止支持 python2 你需要使用这样的命令!
但是不要忘记取消链接旧的 python 如果它是预安装的。
brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/86a44a0a552c673a05f11018459c9f5faae3becc/Formula/python@2.rb
如果您犯了错误,只需brew uninstall python@2
老办法,然后重试。
我 运行 使用带有 flask_mqtt
扩展名的 Flask 解决了这个问题。解决方案是将其添加到 Python 文件中:
app.config['MQTT_TLS_VERSION'] = ssl.PROTOCOL_TLSv1_2
我将 REST API 用于 Cisco CMX device,并尝试编写 Python 代码以向 API 发出获取信息的 GET 请求。代码如下,除必要信息有所改动外,与文件中的相同。
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()
但是,我不断收到以下错误:
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)
我也尝试更新 OpenSSL,但没有效果。
我相信 TLSV1_ALERT_PROTOCOL_VERSION
提醒您服务器不想与您交谈 TLS v1.0。尝试仅通过坚持这些行来指定 TLS v1.2:
import ssl
from http.client import HTTPSConnection
context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
# Create HTTPS connection
c = HTTPSConnection("0.0.0.0", context=context)
请注意,您可能需要足够新的 Python 版本(也许是 2.7.9+?),可能还需要 OpenSSL(我有“OpenSSL 1.0.2k 26 Jan 2017”,以上版本似乎有效,YMMV )
我有同样的错误,google让我想到了这个问题,所以这就是我所做的,希望它能帮助处于类似情况的其他人。
这适用于 OS X。
在终端中检查我使用的是哪个版本的 OpenSSL:
$ python3 -c "import ssl; print(ssl.OPENSSL_VERSION)"
>> OpenSSL 0.9.8zh 14 Jan 2016
由于我的 OpenSSL 版本太旧,接受的答案无效。
所以我不得不更新 OpenSSL。为此,我按照建议的一些步骤 here:
使用 Homebrew 将 Python 更新到最新版本(从 3.5 版到 3.6 版)$ brew update
$ brew install openssl
$ brew install python3
然后我遇到了 PATH 和正在使用的 python 版本的问题,所以我创建了一个新的 virtualenv
确保采用了最新版本的 python :
$ virtualenv webapp --python=python3.6
问题已解决。
None 的已接受答案为我指明了正确的方向,这仍然是搜索主题时出现的问题,所以这是我(部分)成功的传奇。
背景:我 运行 Beaglebone Black 上的 Python 脚本使用 python-poloniex 库轮询加密货币交易所 Poloniex。它突然停止工作并出现 TLSV1_ALERT_PROTOCOL_VERSION 错误。
事实证明 OpenSSL 没问题,而试图强制建立 v1.2 连接是一个巨大的徒劳的尝试 - 该库将根据需要使用最新版本。链中的弱 link 实际上是 Python,它只定义了 ssl.PROTOCOL_TLSv1_2
,因此从 3.4 版本开始支持 TLS v1.2。
同时,Beaglebone 上的 Debian 版本认为 Python 3.3 是最新的。我使用的解决方法是从源代码安装 Python 3.5(3.4 最终可能也能工作,但经过数小时的反复试验后我完成了):
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
也许并非所有这些软件包都是绝对必要的,但一次安装它们可以节省大量重试。 altinstall
防止安装破坏现有的 python 二进制文件,而是安装为 python3.5
,尽管这确实意味着您必须重新安装其他库。 ./configure
花了整整五到十分钟。 make
花了几个小时。
直到我终于运行
,这仍然没有用sudo -H pip3.5 install requests[security]
它还会安装 pyOpenSSL
、cryptography
和 idna
。我怀疑 pyOpenSSL
是关键,所以也许 pip3.5 install -U pyopenssl
就足够了,但我已经花了太长时间来确定这一点。
总而言之,如果您在 Python 中遇到 TLSV1_ALERT_PROTOCOL_VERSION 错误,可能是因为您不支持 TLS v1.2。要添加支持,您至少需要以下内容:
- OpenSSL 1.0.1
- Python 3.4
- 请求[安全]
这让我过去了 TLSV1_ALERT_PROTOCOL_VERSION,现在我开始与 SSL23_GET_SERVER_HELLO 战斗。
原来这又回到了最初的问题 Python 选择了错误的 SSL 版本。这可以通过使用 this 技巧通过 ssl_version=ssl.PROTOCOL_TLSv1_2
安装请求会话来确认。没有它,将使用 SSLv23 并出现 SSL23_GET_SERVER_HELLO 错误。有了它,请求就成功了。
最后的战斗是在第三方库深处提出请求时强制选择 TLSv1_2。 this method and this method 都应该可以解决问题,但两者都没有任何区别。我的最终解决方案很糟糕,但很有效。我编辑了 /usr/local/lib/python3.5/site-packages/urllib3/util/ssl_.py
并更改了
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
至
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
瞧,我的脚本终于可以再次联系服务器了。
您唯一需要做的就是在您的 virtualenv 中安装 requests[security]
。您不必使用 Python 3(它应该在 Python 2.7 中工作)。此外,如果您使用的是最新版本的 macOS,您也不必使用 homebrew
单独安装 OpenSSL。
$ 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]
允许请求在协商连接时使用最新版本的 TLS。 built-in macOS 上的 openssl 支持 TLS v1.2。
Before you install your own version of OpenSSL, ask this question: how is Google Chrome loading https://github.com?
对于Mac OS X
1) 使用从官方 Python 语言网站下载的本机应用程序安装程序更新到 Python 3.6.5 https://www.python.org/downloads/
我发现安装程序正在为新 Python 更新链接和符号链接,这比自制软件要好得多。
2) 使用刷新后的 Python 3.6 目录
中的“./Install Certificates.command”安装新证书> cd "/Applications/Python 3.6/"
> sudo "./Install Certificates.command"
自 2018 年 7 月起,Pypi 现在要求连接到它的客户端使用 TLS 1.2。如果您使用的是 MacOS (2.7.10) 附带的 python 版本,这是一个问题,因为它仅支持 TLS 1.0。您可以更改 python 正在使用的 ssl 版本来解决问题或升级到更新版本的 python。使用 homebrew 在默认库位置之外安装 python 的新版本。
brew install python@2
我也遇到了这个问题。 在 macos 中,这里是解决方案:
第 1 步:brew restall python。现在你得到了 python3.7 而不是旧的 python
第 2 步:基于 python3.7 构建新环境。我的路径是
/usr/local/Cellar/python/3.7.2/bin/python3.7
现在,你不会被这个问题打扰了。
我在尝试 gem install bundler
时遇到了这个问题,我对所有 Python 的响应感到困惑(因为我使用的是 Ruby)。这是我的确切错误:
ERROR: Could not find a valid gem 'bundler' (>= 0), here is why:
Unable to download data from https://rubygems.org/ - SSL_connect returned=1 errno=0 state=SSLv2/v3 read server hello A: tlsv1 alert protocol version (https://rubygems.org/latest_specs.4.8.gz)
我的解决方案:我将 Ruby 更新到最新版本 (2.6.5)。问题已解决。
此问题的另一个来源:我发现在 Debian 9 中,Python httplib2 被硬编码为坚持使用 TLS v1.0。因此,任何使用 httplib2 连接到坚持更高安全性的服务器的应用程序都会失败,并显示 TLSV1_ALERT_PROTOCOL_VERSION.
我通过更改
修复了它context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
至
context = ssl.SSLContext()
在 /usr/lib/python3/dist-packages/httplib2/__init__.py .
Debian 10 没有这个问题。
对于 python2 用户 MacOS (python@2 公式将获胜'找不到),因为 brew 停止支持 python2 你需要使用这样的命令! 但是不要忘记取消链接旧的 python 如果它是预安装的。
brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/86a44a0a552c673a05f11018459c9f5faae3becc/Formula/python@2.rb
如果您犯了错误,只需brew uninstall python@2
老办法,然后重试。
我 运行 使用带有 flask_mqtt
扩展名的 Flask 解决了这个问题。解决方案是将其添加到 Python 文件中:
app.config['MQTT_TLS_VERSION'] = ssl.PROTOCOL_TLSv1_2