SSLError:糟糕的握手,Python请求

时间:2015-12-04 09:58:46

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

我正在使用Ebay Trading APIs消费Ebay python sdkpython-requests最终会点cacert.pem file进行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. 传递参​​数verify = False
  2. 通过CA证书
  3. 在{{3}}中附加CA证书(我试过这个,但没有用)
  4. 我不能这样做是因为:

    1. 请求由第三方库调用,该库位于我的virtualenvirinent中。
    2. 从安全角度来看这是不好的。
    3. 此外,

      1. 我可以使用请求在同一个virtualenv中进行其他TSL调用(例如Amazon marketplace apis),这不会导致不良握手或任何其他SSL错误。
      2. Ebay SDK在我的本地系统(Mac OsX)上工作正常,问题只出在我的生产服务器上(Google Cloud / Debian)
      3. 我的域上没有Chrome报告的SSL错误
      4. 我不知道为什么会这样。

        当我禁用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
        

2 个答案:

答案 0 :(得分:2)

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

要修复此问题而不更改您的可信CA,您需要有一个固定的OpenSSL,即OpenSSL 1.0.2。或者您可以将一些旧的CA证书添加回您的信任存储区。

  
      
  1. 传递参​​数verify = False
  2.   
  3. 通过CA证书
  4.   
  5. 在cacert.pem文件中附加CA证书(我试过这个,但没有用)
  6.         

    ...   从安全角度来看这是不好的。

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

  当我禁用SSL3时,

为什么SSL例程','SSL3_GET_SERVER_CERTIFICATE','证书验证失败'处于追溯状态。

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

答案 1 :(得分:0)

我认为它与https://pypi.python.org/pypi/certifi/

的这一部分有关
  

1024位根证书

     

浏览器和证书颁发机构   得出的结论是,1024位密钥对于证书来说是不可接受的,   特别是根证书。出于这个原因,Mozilla已经删除了   来自其捆绑包的任何弱(即1024位密钥)证书,替换它   具有等效的强(即2048位或更高的密钥)证书   来自同一个CA.因为Mozilla从其中删除了这些证书   捆绑,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)

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

# 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