2013-07-06 52 views
6

我試圖使用Python 2.7 mechanize登錄到Mint.com用下面的代碼:Python的SSL登錄掛在Debian

import mechanize 
br = mechanize.Browser() 
br.open("https://wwws.mint.com/login.event") 

這只是正常的OSX,但它Debian上掛起。這個問題似乎與ssl有關;回溯與

File "/usr/lib/python2.7/ssl.py", line 305, in do_handshake 
    self._sslobj.do_handshake() 

編輯結束:在Debian使用urllib2 的問題仍然存在。正如評論中所建議的那樣,這個問題似乎與ssl有關。爲什麼這會成爲Debian而不是OSX的問題?

+0

我認爲這與機械化本身無關,它與python stdlib有關 - 請參閱[這個問題](http://bugs.python.org/issue1251)。 – alecxe

+0

@alecxe非常感謝,這似乎確實適用。然而,根據該線程,這個問題應該修補......這顯然不是。任何想法我能做些什麼來讓事情發揮作用?另外,如果這個錯誤導致了這個問題,那麼這對OSX也不是問題,因爲它們都是Python 2.7.3? – rickcnagy

+0

好吧,這很難說。該代碼適用於我在Ubuntu 12.04上使用python 2.7.3。 – alecxe

回答

1

所以事情看起來確定在Fedora:

[[email protected] ~]$ python 
Python 2.7.5 (default, Aug 22 2013, 09:31:58) 
[GCC 4.8.1 20130603 (Red Hat 4.8.1-1)] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import mechanize 
>>> br = mechanize.Browser() 
>>> br.open("https://wwws.mint.com/login.event") 
<response_seek_wrapper at 0x29b6440 whose wrapped object = <closeable_response at 0x29b6320 whose fp = <socket._fileobject object at 0x298d150>>> 
>>> br.title() 
'Mint > Start Here' 
>>> 

這使我想知道的SSL /使用OpenSSL庫。只是爲了測試它,你可以在命令行中運行:

$ openssl s_client -connect wwws.mint.com:443 

您應該看到顯示薄荷的SSL證書,擁有完整證書鏈驗證一起,和最後一行:「驗證返回碼:0(好吧)「

雖然我高度懷疑這是一個SSL問題直接我認爲這是值得檢查。此外,請驗證機械化的版本。 Debian着名的是使用穩定版本的代碼(不是新版本)。我通過機械化驗證的版本是0.2.5

1

這是最近版本的OpenSSL和某些Web服務器之間不兼容的體現。蘋果公司正盡最大努力消除OS X上的OpenSSL,所以他們只使用安全補丁(作爲操作系統的一部分,OpenSSL一直難以支持,更不用說引入像這樣的問題的「次要」更新),而Debian正在使用一個更新的OpenSSL 1.0.1。

@Brian Redbeard的建議檢查openssl命令行是一個很好的建議 - 它掛在我wwws.mint.com當我剛剛嘗試它。

This question在ServerFault上終於提供了答案。鏈接到那裏的SSLLabs測試將確定long handshake intolerance作爲影響OpenSSL 1.0.1和更高版本的問題,並指向具有一些潛在解決方法的OpenSSL bug

或者使用-no_tls1_2,爲OpenSSL的開發商一個建議,或減少與-cipher參數的密碼列表,使OpenSSL的1.0.1與wwws.mint.com成功握手(以及另一臺服務器,我試圖聯繫)。

對於我而言 - 是不會腳本來進行分配 - 我monkeypatched ssl.wrap_socket如下:

import ssl 
old_wrap_socket = ssl.wrap_socket 
def wrap_socket(sock, keyfile=None, certfile=None, 
       server_side=False, cert_reqs=ssl.CERT_NONE, 
       ssl_version=ssl.PROTOCOL_SSLv3, ca_certs=None, 
       do_handshake_on_connect=True, 
       suppress_ragged_eofs=True, ciphers=None): 
    return old_wrap_socket(sock, keyfile, certfile, 
          server_side, cert_reqs, ssl_version, 
          ca_certs, do_handshake_on_connect, 
          suppress_ragged_eofs, ciphers) 
ssl.wrap_socket = wrap_socket 

import mechanize 

ssl_version的默認值是ssl.PROTOCOL_SSLv23;通過將其更改爲PROTOCOL_SSLv3它成功連接。

您可以使用諸如ssl.OPENSSL_VERSION_INFO[:3] >= (1, 0, 1)的測試來防範此修補程序。

如果尚未發佈,可能會將其報告爲Debian OpenSSL錯誤。