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

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

问题描述

我一直在尝试使用 requests 在 Python 3 中执行 HTTPS 请求,并汇总了 StackOverflow 上记录的先前尝试中的几乎所有知识.我似乎一辈子都无法摆脱 sslv3 警报握手失败 兔子洞.

这是我的环境:

  • 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]
  • 安装的
  • requests 2.19.1(print(requests.__version__) 的输出)
  • 甚至安装了密码学 2.3.1

这是基本的失败代码:

<预><代码>>>>进口请求>>>requests.get('https://iris.nuigalway.ie')

这是输出:

回溯(最近一次调用最后一次):文件/usr/local/lib/python3.7/site-packages/urllib3-1.23-py3.7.egg/urllib3/contrib/pyopenssl.py",第 444 行,在 wrap_socketcnx.do_handshake()文件/usr/local/lib/python3.7/site-packages/pyOpenSSL-18.0.0-py3.7.egg/OpenSSL/SSL.py",第 1907 行,在 do_handshake 中self._raise_ssl_error(self._ssl,结果)文件/usr/local/lib/python3.7/site-packages/pyOpenSSL-18.0.0-py3.7.egg/OpenSSL/SSL.py",第 1639 行,_raise_ssl_error_raise_current_error()文件/usr/local/lib/python3.7/site-packages/pyOpenSSL-18.0.0-py3.7.egg/OpenSSL/_util.py",第54行,在exception_from_error_queue引发异常类型(错误)OpenSSL.SSL.Error: [('SSL 例程', 'ssl3_read_bytes', 'sslv3 警报握手失败')]

不用说它适用于 cURL、浏览器等.

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

这是输出的握手片段:

* ALPN,提供 h2* ALPN,提供http/1.1* 密码选择:ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH* 成功设置证书验证位置:* CA文件:/etc/ssl/cert.pemCApath:无* TLSv1.2 (OUT), TLS 握手, 客户端问候 (1):* TLSv1.0 (IN)、TLS 握手、服务器问候 (2):* TLSv1.0 (IN)、TLS 握手、证书 (11):* TLSv1.0 (IN), TLS 握手, 服务器完成 (14):* TLSv1.0 (OUT)、TLS 握手、客户端密钥交换 (16):* TLSv1.0 (OUT), TLS 更改密码, Client hello (1):* TLSv1.0 (OUT),TLS 握手,完成 (20):* TLSv1.0 (IN)、TLS 更改密码、客户端问候 (1):* TLSv1.0 (IN),TLS 握手,完成 (20):* SSL 连接使用 TLSv1.0/DES-CBC3-SHA* ALPN,服务器不同意协议

现在 cURL 使用的密码似乎确实不是 urllib3 1.23(似乎被 requests 使用)的默认密码之一://github.com/urllib3/urllib3/blob/1.23/urllib3/util/ssl_.py" rel="nofollow noreferrer">https://github.com/urllib3/urllib3/blob/1.23/urllib3/util/ssl_.py

所以我尝试使用 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 版本和密码:

新,TLSv1/SSLv3,密码是RC4-SHA服务器公钥为 2048 位支持安全重新协商压缩:无扩展:无没有协商 ALPNSSL 会话:协议:TLSv1密码:RC4-SHA

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

非常感谢

更新

ssl.OPENSSL_VERSION 的值 OpenSSL.SSL.SSLeay_version(0) 揭示了 ssl 使用的两个不同版本的 OpenSSL>pyOpenSSL,后者是更新的 OpenSSL 1.1.0i 2018 年 8 月 14 日,它很可能已经放弃了对 DES-CBC3-SHA 密码的支持.

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

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

(注意不再是串联)

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

我很欣赏这个解决方案可能不是最优的并且不适用于很多情况,但至少吸取的教训是不同版本的 OpenSSL 可能会从一个包到另一个包起作用.

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

解决方案

服务器好像真的坏了.如果您只是将 DES-CBC3-SHA 添加到密码列表中,它将无法正常工作,可能是因为服务器因客户端提供服务器不知道的密码或密码太多而导致服务器发出嘶嘶声.>

如果改为只允许使用这个单一密码,它对我有用,即

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

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.

This is my environment:

  • 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

This is the bare-bone failing code:

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

And this is the output:

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')]

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

Now the cipher used by cURL does not indeed seem to be among the default ciphers of urllib3 1.23 (seemingly used by requests) as per https://github.com/urllib3/urllib3/blob/1.23/urllib3/util/ssl_.py

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'

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)

A check with s_client on the server:

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

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?

Many Thanks

UPDATE

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. uninstall cryptography
  2. injecting only the required cipher, like this:

(Note that it is no longer a concatenation)

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

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.

解决方案

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天全站免登陆