【问题标题】:SSLError: bad handshake, Python requestsSSLError:糟糕的握手,Python 请求
【发布时间】:2015-12-04 09:58:46
【问题描述】:

我正在使用Ebay python sdk 消费Ebay Trading APIs,它最终会使用python-requests 进行API 调用。

一切正常,但最近几天我无法拨打电话。我收到错误:

SSLError: bad handshake: Error([('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE', 'certificate verify failed')],)

这是完整的回溯:

In [9]: response = api.execute('GetSessionID', data)
---------------------------------------------------------------------------
SSLError                                  Traceback (most recent call last)
<ipython-input-9-eb33610c2a7f> in <module>()
----> 1 response = api.execute('GetSessionID', data)

/home/debian/.virtualenvs/myvirtualenv/local/lib/python2.7/site-packages/ebaysdk/connection.pyc in execute(self, verb, data, list_nodes, verb_attrs, files)
    117
    118         self.build_request(verb, data, verb_attrs, files)
--> 119         self.execute_request()
    120
    121         if hasattr(self.response, 'content'):

/home/debian/.virtualenvs/goplaces/local/lib/python2.7/site-packages/ebaysdk/connection.pyc in execute_request(self)
    182             proxies=self.proxies,
    183             timeout=self.timeout,
--> 184             allow_redirects=True
    185         )
    186

/home/debian/.virtualenvs/myvirtualenv/local/lib/python2.7/site-packages/requests/sessions.pyc in send(self, request, **kwargs)
    574
    575         # Send the request
--> 576         r = adapter.send(request, **kwargs)
    577
    578         # Total elapsed time of the request (approximately)

/home/debian/.virtualenvs/myvirtualenv/local/lib/python2.7/site-packages/requests/adapters.pyc in send(self, request, stream, timeout, verify, cert, proxies)
    431         except (_SSLError, _HTTPError) as e:
    432             if isinstance(e, _SSLError):
--> 433                 raise SSLError(e, request=request)
    434             elif isinstance(e, ReadTimeoutError):
    435                 raise ReadTimeout(e, request=request)

SSLError: bad handshake: Error([('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE', 'certificate verify failed')],)

StackOverflow 上有很多相关的问题,都说:

  1. 传递参数验证=假
  2. 通过CA证书
  3. cacert.pem file 中附加您的 CA 证书(我试过了,没用)

我不能这样做,因为:

  1. requests 正在被我的 virtualenvirinent 中的第三方库调用。
  2. 从安全角度来看,这很糟糕。

还有,

  1. 我可以使用请求在同一个虚拟环境中进行其他 TSL 调用(例如亚马逊市场 API),这不会导致握手错误或任何其他 SSL 错误。
  2. Ebay SDK 在我的本地系统 (Mac OsX) 上运行良好,仅在我的生产服务器 (Google Cloud/Debian) 上出现问题
  3. Chrome 在我的域上没有报告 SSL 错误

我不知道为什么会这样。

当我禁用 SSL3 时,为什么 SSL routines', 'SSL3_GET_SERVER_CERTIFICATE', 'certificate verify failed' 处于回溯状态。 (我对 SSL 没有深入的了解)。

谢谢!

编辑:

# openssl version
OpenSSL 1.0.2e 3 Dec 2015

根据@Steffen Ullrich 的建议从源代码构建,从 1.0.1 升级到 openssl 1.0.2。

$ pip freeze | grep -i ssl
backports.ssl-match-hostname==3.4.0.2
pyOpenSSL==0.15.1

【问题讨论】:

标签: python django ssl python-requests ebay-api


【解决方案1】:

我的猜测是这与Python Urllib2 SSL error有关,即OpenSSL底层实现中的多信任路径问题。有关问题的详细信息,请参见那里。

要在不更改您受信任的 CA 的情况下解决此问题,您需要有一个固定的 OpenSSL,即 OpenSSL 1.0.2。或者,您可以将一些较旧的 CA 证书添加回您的信任库。

  1. 传递参数验证=False
  2. 通过CA证书
  3. 在 cacert.pem 文件中附加你的 CA 证书(我试过了,没用)

... 从安全角度来看,这很糟糕。

虽然verify=False 对安全性不利,因为它禁用了验证,但其他选项也不错,因为它们只添加了额外的信任锚但保持启用验证。

当我禁用 SSL3 时,为什么 SSL 例程、“SSL3_GET_SERVER_CERTIFICATE”、“证书验证失败”在回溯中。

即使它在那里谈论 SSLv3,也不是这个意思。 TLS 和 SSLv3 共享很多功能,即 TLS 1.0 实际上是 SSL 3.1。因此,OpenSSL 代码中的许多 SSL3_* 函数也与 TLS 1.x 一起使用,这会导致这些恼人的消息。

【讨论】:

  • 升级到 openssl 1.0.2 ,问题依旧。我想指出我可以向其他 api 发出请求,例如来自同一个 virtualenv 的亚马逊。
  • @electropoet:您能否分享一个最小的工作示例,以便重现您的问题?现在只是猜测问题可能是什么。
【解决方案2】:

我觉得和https://pypi.python.org/pypi/certifi/的这一段有关

1024 位根证书

浏览器和证书颁发机构有 得出的结论是 1024 位密钥对于证书来说太弱了,无法接受, 特别是根证书。因此,Mozilla 已删除 其捆绑包中的任何弱(即 1024 位密钥)证书,替换它 具有等效的强(即 2048 位或更大密钥)证书 来自同一个 CA。因为 Mozilla 从其 bundle,certifi 也删除了它们。

不幸的是,旧版本的 OpenSSL(低于 1.0.2)有时 无法验证使用强根的证书链。为了 因此,如果您无法使用 certifi.where() 机制,可以有意重新添加1024位 通过调用 certifi.old_where() 来重新扎根到你的包中。 不建议在生产中这样做:如果可能的话,你应该 升级到更新的 OpenSSL。但是,如果您别无选择,这 可能对你有用。

我的测试是这样的:

root@43b7ec35c240:/usr/src/app# cat /etc/debian_version
8.2
root@43b7ec35c240:/usr/src/app# cat test.py
import logging

import requests

logging.basicConfig()
logging.getLogger().setLevel(logging.DEBUG)
requests_log = logging.getLogger("requests.packages.urllib3")
requests_log.setLevel(logging.DEBUG)
requests_log.propagate = True

requests.get('https://www.google.com/')
root@43b7ec35c240:/usr/src/app# python test.py
INFO:requests.packages.urllib3.connectionpool:Starting new HTTPS connection (1): www.google.com
DEBUG:requests.packages.urllib3.connectionpool:"GET / HTTP/1.1" 302 263
INFO:requests.packages.urllib3.connectionpool:Starting new HTTPS connection (1): www.google.com.hk
DEBUG:requests.packages.urllib3.connectionpool:"GET /?gfe_rd=cr&ei=XXKbVqqBD8WM8Qe3v7-YAQ HTTP/1.1" 200 None
root@43b7ec35c240:/usr/src/app# openssl version
OpenSSL 1.0.1k 8 Jan 2015
root@43b7ec35c240:/usr/src/app# pip install certifi
Collecting certifi
  Using cached certifi-2015.11.20.1-py2.py3-none-any.whl
Installing collected packages: certifi
Successfully installed certifi-2015.11.20.1
root@43b7ec35c240:/usr/src/app# python test.py
INFO:requests.packages.urllib3.connectionpool:Starting new HTTPS connection (1): www.google.com
Traceback (most recent call last):
  File "test.py", line 16, in <module>
    requests.get('https://www.google.com/')
  File "/usr/local/lib/python2.7/site-packages/requests/api.py", line 69, in get
    return request('get', url, params=params, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/requests/api.py", line 50, in request
    response = session.request(method=method, url=url, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/requests/sessions.py", line 468, in request
    resp = self.send(prep, **send_kwargs)
  File "/usr/local/lib/python2.7/site-packages/requests/sessions.py", line 576, in send
    r = adapter.send(request, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/requests/adapters.py", line 433, in send
    raise SSLError(e, request=request)
requests.exceptions.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:590)
root@43b7ec35c240:/usr/src/app# pip uninstall certifi
Uninstalling certifi-2015.11.20.1:
  /usr/local/lib/python2.7/site-packages/certifi-2015.11.20.1.dist-info/DESCRIPTION.rst
  /usr/local/lib/python2.7/site-packages/certifi-2015.11.20.1.dist-info/METADATA
  /usr/local/lib/python2.7/site-packages/certifi-2015.11.20.1.dist-info/RECORD
  /usr/local/lib/python2.7/site-packages/certifi-2015.11.20.1.dist-info/WHEEL
  /usr/local/lib/python2.7/site-packages/certifi-2015.11.20.1.dist-info/metadata.json
  /usr/local/lib/python2.7/site-packages/certifi-2015.11.20.1.dist-info/top_level.txt
  /usr/local/lib/python2.7/site-packages/certifi/__init__.py
  /usr/local/lib/python2.7/site-packages/certifi/__init__.pyc
  /usr/local/lib/python2.7/site-packages/certifi/__main__.py
  /usr/local/lib/python2.7/site-packages/certifi/__main__.pyc
  /usr/local/lib/python2.7/site-packages/certifi/cacert.pem
  /usr/local/lib/python2.7/site-packages/certifi/core.py
  /usr/local/lib/python2.7/site-packages/certifi/core.pyc
  /usr/local/lib/python2.7/site-packages/certifi/old_root.pem
  /usr/local/lib/python2.7/site-packages/certifi/weak.pem
Proceed (y/n)? y
  Successfully uninstalled certifi-2015.11.20.1
root@43b7ec35c240:/usr/src/app# python test.py
INFO:requests.packages.urllib3.connectionpool:Starting new HTTPS connection (1): www.google.com
DEBUG:requests.packages.urllib3.connectionpool:"GET / HTTP/1.1" 302 263
INFO:requests.packages.urllib3.connectionpool:Starting new HTTPS connection (1): www.google.com.hk
DEBUG:requests.packages.urllib3.connectionpool:"GET /?gfe_rd=cr&ei=AnObVtG4BcGM8QeC6r-YCw HTTP/1.1" 200 None

然后我尝试通过以下方式更新我的 libssl 包:

# curl http://apt.wikimedia.org/autoinstall/keyring/wikimedia-archive-keyring.gpg | apt-key add -

# echo "deb http://apt.wikimedia.org/wikimedia jessie-wikimedia backports" >> /etc/apt/sources.list

# apt-get update
# apt-get install libssl1.0.0

# openssl version
OpenSSL 1.0.1k 8 Jan 2015 (Library: OpenSSL 1.0.2e 3 Dec 2015)

在那之后,即使安装了证书,我也很好。

# pip freeze |grep certifi
certifi==2015.11.20.1

# python test.py
INFO:requests.packages.urllib3.connectionpool:Starting new HTTPS connection (1): www.google.com
DEBUG:requests.packages.urllib3.connectionpool:"GET / HTTP/1.1" 302 263
INFO:requests.packages.urllib3.connectionpool:Starting new HTTPS connection (1): www.google.com.hk
DEBUG:requests.packages.urllib3.connectionpool:"GET /?gfe_rd=cr&ei=4XSbVt2gK8OM8Qe1tICIBA HTTP/1.1" 200 None

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-13
    • 2018-08-16
    • 1970-01-01
    • 1970-01-01
    • 2017-11-24
    相关资源
    最近更新 更多