使用urllib2时出现SSLv3握手失败警告

5

我在使用Python 2.7.10中的urllib2连接https时遇到了麻烦。

您有什么想法,我可能漏掉了什么?

Python 2.7.10 (default, Jun 18 2015, 10:53:24) 
[GCC 4.4.5] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import ssl, urllib2
>>> ssl.HAS_SNI
True
>>> ssl.OPENSSL_VERSION
'OpenSSL 0.9.8o 01 Jun 2010'
>>> opener = urllib2.build_opener()
>>> opener.open('https://twitrss.me/')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/python2.7/lib/python2.7/urllib2.py", line 431, in open
    response = self._open(req, data)
  File "/usr/local/python2.7/lib/python2.7/urllib2.py", line 449, in _open
    '_open', req)
  File "/usr/local/python2.7/lib/python2.7/urllib2.py", line 409, in _call_chain
    result = func(*args)
  File "/usr/local/python2.7/lib/python2.7/urllib2.py", line 1240, in https_open
    context=self._context)
  File "/usr/local/python2.7/lib/python2.7/urllib2.py", line 1197, in do_open
    raise URLError(err)
urllib2.URLError: <urlopen error [SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure (_ssl.c:590)>

这个问题在我使用Python 2.7.10的Windows上没有发生。但是在我使用Python 2.7.11的OS X上发生了。我正在尝试打开PayPal。 - user2233706
我已确认此问题在使用Python 2.7.10的OS X上发生。因此,在使用Python 2.7.10的Windows上运行正常。 - user2233706
1个回答

2
我能够在OS X 10.10.3上复制您的问题,其原生Python版本为2.7.6,使用的OpenSSL版本为0.9.8zd。
问题出在TLS握手中缺少服务器名称指示(SNI)扩展,而twitrss.me网站显然需要该扩展:

服务器名称指示(SNI)是TLS计算机网络协议的一种扩展,客户端在握手过程开始时指示其正在尝试连接的主机名。

我通过编写一个使用OpenSSL的小型C++程序并插入OpenSSL调用来验证了这一点。
SSL_set_tlsext_host_name(ssl, "twitrss.me");

允许成功连接而忽略失败。我还查看了数据包转储以验证使用Python尝试连接时是否缺少SNI。

Python SSL模块显然支持Python 3中的SNI,但在Python 2中可能需要解决方法。似乎PEP 0466 包括SNI,并在 Python 2.7.9 中实现,因此您应该拥有它,但我不知道 urllib2 / urllib3 是否利用此功能而无需解决方法。


1
我通过编写一个小的C++程序进行了验证... openssl s_client -connect twitrss.me:443 -tls1 -servername twitrss.me 也可以正常工作。无需编程。 -servername 是SNI选项。 - jww

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接