python3和请求:仍会收到“ sslv3警报握手失败”

时间:2018-08-23 18:10:13

标签: python python-3.x ssl openssl python-requests

我一直在尝试使用requests在Python 3中执行HTTPS请求,并汇总了StackOverflow上记录的先前尝试中的几乎所有知识。我似乎一生无法摆脱sslv3 alert handshake failure兔子洞。

这是我的环境:

  • macOS 10.13.6
  • Python 3.7.0(通过Homebrew与openssl一起安装)
  • OpenSSL 1.0.2p 2018年8月14日(print(ssl.OPENSSL_VERSION)的输出)
  • 通过print(requests.__version__)安装的
  • 请求2.19.1(pip install requests[security]的输出)
  • 已安装平均密码2.3.1

这是失败的原始代码:

>>> import requests
>>> requests.get('https://iris.nuigalway.ie')

这是输出:

Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/urllib3-1.23-py3.7.egg/urllib3/contrib/pyopenssl.py", line 444, in wrap_socket
    cnx.do_handshake()
  File "/usr/local/lib/python3.7/site-packages/pyOpenSSL-18.0.0-py3.7.egg/OpenSSL/SSL.py", line 1907, in do_handshake
    self._raise_ssl_error(self._ssl, result)
  File "/usr/local/lib/python3.7/site-packages/pyOpenSSL-18.0.0-py3.7.egg/OpenSSL/SSL.py", line 1639, in _raise_ssl_error
    _raise_current_error()
  File "/usr/local/lib/python3.7/site-packages/pyOpenSSL-18.0.0-py3.7.egg/OpenSSL/_util.py", line 54, in exception_from_error_queue
    raise exception_type(errors)
OpenSSL.SSL.Error: [('SSL routines', 'ssl3_read_bytes', 'sslv3 alert handshake failure')]

不用说它可与cURL,浏览器等配合使用。

curl --verbose "https://iris.nuigalway.ie"

以下是输出的握手摘要:

* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/cert.pem
  CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.0 (IN), TLS handshake, Server hello (2):
* TLSv1.0 (IN), TLS handshake, Certificate (11):
* TLSv1.0 (IN), TLS handshake, Server finished (14):
* TLSv1.0 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.0 (OUT), TLS change cipher, Client hello (1):
* TLSv1.0 (OUT), TLS handshake, Finished (20):
* TLSv1.0 (IN), TLS change cipher, Client hello (1):
* TLSv1.0 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.0 / DES-CBC3-SHA
* ALPN, server did not agree to a protocol

现在,根据https://github.com/urllib3/urllib3/blob/1.23/urllib3/util/ssl_.py,cURL所使用的密码实际上似乎并不属于urllib3 1.23(似乎由requests使用的默认密码)

所以我尝试使用https://stackoverflow.com/a/40741362给出的建议添加它,如下所示:

>>> requests.packages.urllib3.util.ssl_.DEFAULT_CIPHERS += 'DES-CBC3-SHA'

,甚至将其设置为ALL。我什至试图不验证证书,但无济于事。

>>> requests.get('https://iris.nuigalway.ie', verify=False)

在服务器上使用s_client进行支票:

$ openssl s_client -connect iris.nuigalway.ie:443

显示以下TLS版本和密码:

New, TLSv1/SSLv3, Cipher is RC4-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1
    Cipher    : RC4-SHA

我可能还没有尝试过哪些选项?

非常感谢

更新

ssl.OPENSSL_VERSION OpenSSL.SSL.SSLeay_version(0)的值显示了sslpyOpenSSL分别使用的两个不同版本的OpenSSL,后者是更新的OpenSSL 1.1.0i 14 Aug 2018,具有最有可能放弃了对DES-CBC3-SHA密码的支持。

以下是我采用的临时解决方案:

  1. 卸载cryptography
  2. 仅注入所需的密码,如下所示:

(请注意,它不再是串联的)

requests.packages.urllib3.util.ssl_.DEFAULT_CIPHERS = 'DES-CBC3-SHA'

我知道该解决方案可能不是最优的,并且不适用于许多情况,但是至少吸取的教训是,从一个软件包到另一个软件包,可能正在使用不同版本的OpenSSL。

如果有更灵活的解决方案,我将很高兴。

1 个答案:

答案 0 :(得分:1)

服务器似乎真的坏了。如果仅将DES-CBC3-SHA添加到密码列表中,它将无法正常工作,这可能是因为服务器崩溃了,原因是客户端提供了服务器不知道的密码,或者是因为密码太多。

如果将其更改为仅允许使用此单个密​​码,则它对我有用,即

requests.packages.urllib3.util.ssl_.DEFAULT_CIPHERS = 'DES-CBC3-SHA'