您将如何强制mechanize将SSLv3用于需要它的HTTPS URL?如果我尝试使用所有的SSLv3只机械化的网址,我得到的错误:强制机械化使用SSLv3
URLError: <urlopen error [Errno 1] _ssl.c:504: error:140773E8:SSL routines:SSL23_GET_SERVER_HELLO:reason(1000)>
您将如何强制mechanize将SSLv3用于需要它的HTTPS URL?如果我尝试使用所有的SSLv3只机械化的网址,我得到的错误:强制机械化使用SSLv3
URLError: <urlopen error [Errno 1] _ssl.c:504: error:140773E8:SSL routines:SSL23_GET_SERVER_HELLO:reason(1000)>
Eiyrioü冯Kauyf上面提到的Python的问题的最后注释是我在forked version of mechanize实施的解决方案。 mechanize/_opener.py的差异如下。它修复mechanize.urlopen(),但“不是mechanize.Browser()open()方法:
diff --git a/mechanize/_opener.py b/mechanize/_opener.py
index ad8412d..e6d1ebc 100644
--- a/mechanize/_opener.py
+++ b/mechanize/_opener.py
@@ -25,9 +25,27 @@ import _rfc3986
import _sockettimeout
import _urllib2_fork
from _util import isstringlike
+import ssl, socket
open_file = open
+class HTTPSConnectionV3(httplib.HTTPSConnection):
+ def __init__(self, *args, **kwargs):
+ httplib.HTTPSConnection.__init__(self, *args, **kwargs)
+
+ def connect(self):
+ sock = socket.create_connection((self.host, self.port), self.timeout)
+ if self._tunnel_host:
+ self.sock = sock
+ self._tunnel()
+ try:
+ self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file, ssl_version=ssl.PROTOCOL_SSLv3)
+ except ssl.SSLError, e:
+ self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file, ssl_version=ssl.PROTOCOL_SSLv23)
+
+class HTTPSHandlerV3(urllib2.HTTPSHandler):
+ def https_open(self, req):
+ return self.do_open(HTTPSConnectionV3, req)
class ContentTooShortError(urllib2.URLError):
def __init__(self, reason, result):
@@ -370,7 +388,7 @@ class OpenerFactory:
_urllib2_fork.HTTPErrorProcessor,
]
if hasattr(httplib, 'HTTPS'):
- default_classes.append(_urllib2_fork.HTTPSHandler)
+ default_classes.append(HTTPSHandlerV3)
handlers = []
replacement_handlers = []
非常感谢您的支持,它对我有用 – bernie
肮脏的答案......不需要打补丁。
import ssl
from ssl import PROTOCOL_SSLv23, PROTOCOL_SSLv3, CERT_NONE, SSLSocket
def monkey_wrap_socket(sock, keyfile=None, certfile=None,
server_side=False, cert_reqs=CERT_NONE,
ssl_version=PROTOCOL_SSLv23, ca_certs=None,
do_handshake_on_connect=True,
suppress_ragged_eofs=True, ciphers=None):
ssl_version=PROTOCOL_SSLv3
return SSLSocket(sock, keyfile=keyfile, certfile=certfile,
server_side=server_side, cert_reqs=cert_reqs,
ssl_version=ssl_version, ca_certs=ca_certs,
do_handshake_on_connect=do_handshake_on_connect,
suppress_ragged_eofs=suppress_ragged_eofs,
ciphers=ciphers)
ssl.wrap_socket = monkey_wrap_socket
...在您的代码之前。
Hrmm,对我不起作用,我仍然得到主机名不符合certificateerror – pugmastaflex
您可以使用ssl.wrap_socket()来使用TLSv1,它在Poodle漏洞之后似乎是唯一可行的左边。这将强制所有SSL连接使用TLSv1,而不管更高级别的库如何。
import ssl
from functools import wraps
def sslwrap(func):
@wraps(func)
def bar(*args, **kw):
kw['ssl_version'] = ssl.PROTOCOL_TLSv1
return func(*args, **kw)
return bar
ssl.wrap_socket = sslwrap(ssl.wrap_socket)
从下面的错误报告,这可能会帮助: http://bugs.python.org/issue11220 此外,我觉得应该有一个''verify_mode''地方的选择,但我不能在''mechanize''文档中找到它:/。和''def add_client_certificate(self,url,key_file,cert_file):''in mechanize/_useragent.py可能会有所帮助,但抱歉我找不到任何明确使用现在:( –
@EiyrioüvonKauyf,是的,我偶然发现这就是为什么我试图强制它使用SSLv3,“问题是服务器只严格接受SSLv3,urllib和http.client发送SSLv23协议。”他们甚至以自定义的形式为urllib提供了解决方法但我不知道如何适应机械化 – Cerin