python3和请求:仍然出现"sslv3警报握手失败" [英] python3 and requests: still getting 'sslv3 alert handshake failure'

查看:692
本文介绍了python3和请求:仍然出现"sslv3警报握手失败"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have been trying to perform an HTTPS request in Python 3 using requests and aggregating pretty much all the knowledge from the prior attempts documented on StackOverflow. I cannot for the life of me seem to get out of the sslv3 alert handshake failure rabbit hole.

这是我的环境:

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

这是失败的原始代码:

>>> 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,浏览器等配合使用.

Needless to say it works with cURL, browsers etc.

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

以下是输出的握手摘要:

Here's a handshake snippet of the ouput:

* 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

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

So I tried adding it using the advice given at https://stackoverflow.com/a/40741362 like this:

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

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

and even setting it to ALL. I even tried not to verify the certificate, all to no avail.

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

通过服务器上的s_client进行检查:

A check with s_client on the server:

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

显示以下TLS版本和密码:

reveals the following TLS version and cipher:

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

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

What options could I possibly have not tried yet?

非常感谢

更新

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

The values of ssl.OPENSSL_VERSION OpenSSL.SSL.SSLeay_version(0) revealed two different versions of OpenSSL used by ssl and pyOpenSSL respectively, the latter being a more recent OpenSSL 1.1.0i 14 Aug 2018 that has most likely dropped support for the DES-CBC3-SHA cipher.

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

Below is the temporary solution I have adopted:

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

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

(Note that it is no longer a concatenation)

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

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

I appreciate that this solution may be sub-optimal and not applicable to many cases, but at least the lesson learnt is that different versions of OpenSSL may be at play from one package to another.

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

I will be happy to know of a more flexible solution if any.

推荐答案

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

The server seems to be really broken. If you just add DES-CBC3-SHA to the list of ciphers it will not work, maybe because the server croaks because the client offers ciphers the server does not know or because of too much ciphers.

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

If one instead changes it to only allow this single cipher it works for me, i.e.

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

这篇关于python3和请求:仍然出现"sslv3警报握手失败"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆