Python httplib SSL23_GET_SERVER_HELLO:未知协议 [英] Python httplib SSL23_GET_SERVER_HELLO:unknown protocol
问题描述
注意:此代码在Ubuntu上能正常工作,但在Mac上却不能,并且不是在本地更改mac/python设置,而是尝试对代码进行更改,以使其在任何地方都可以使用..
Note: this code works fine on Ubuntu but not on mac and instead of changing the mac/python settings locally I'm trying to make change to the code so it'll work everywhere..
import ssl
import httplib
httplib.HTTPConnection(server, port, timeout)
但是会引发错误:
[Errno 1] _ssl.c:503:错误:140770FC:SSL 例程:SSL23_GET_SERVER_HELLO:未知协议
[Errno 1] _ssl.c:503: error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol
现在代码未使用 urllib.request ,而是使用 httplib
now code's not using urllib.request instead using httplib
我想更改代码,以便它将SSLv3作为默认协议,如下所示:
I want to change the code so it'll take SSLv3 as default protocol, something like this:
ssl.SSLContext(ssl.PROTOCOL_SSLv3)
我环顾四周,发现链接很少,但是没有任何作用!
I looked around and found few links but nothing is working!
推荐答案
Note: The HTTPSConnection constructor allows to pass an ssl context
as argument since python 2.7.9, which should be used in this case.
此答案早于更改,因此仅适用于python的过时版本.
This answer predates that change and therefore only applies to outdated versions of python.
httplib.HTTPSConnection.connect
仅调用 ssl.wrap_socket
来初始化https连接您不能在python2.7中指定任何参数(python3允许通过SSLContext
).
如果要指定协议版本,则需要猴子修补以下两个之一:
If you want to specify the protocol version, you'd need to monkey patch one of these two:
方法1 :补丁httplib.HTTPSConnection.connect
:
import httplib
import socket
import ssl
def connect_patched(self):
"Connect to a host on a given (SSL) port."
sock = socket.create_connection((self.host, self.port),
self.timeout, self.source_address)
if self._tunnel_host:
self.sock = sock
self._tunnel()
self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file,
ssl_version=ssl.PROTOCOL_SSLv3)
httplib.HTTPSConnection.connect = connect_patched
这将更改使用HTTPSConnection
建立的所有连接的协议版本.
This changes the protocol version for all connections made with HTTPSConnection
.
方法2 :补丁ssl.wrap_socket
:
import ssl
wrap_socket_orig = ssl.wrap_socket
def wrap_socket_patched(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 wrap_socket_orig(sock, keyfile, certfile, server_side,
cert_reqs, ssl_version, ca_certs,
do_handshake_on_connect,
suppress_ragged_eofs, ciphers)
ssl.wrap_socket = wrap_socket_patched
这会更改使用wrap_socket
的 all 代码的默认协议版本,因此也会影响其他库.
This changes the default protocol version for all code that uses wrap_socket
, therefore also affects other libraries.
方法3 :因为httplib实际上仅从ssl
访问wrap_socket
,所以您也可以将httplib.ssl
替换为提供wrap_socket
的类.使用functools.partial
使得编写此代码非常优雅:
Method 3: because httplib actually accesses only wrap_socket
from ssl
, you could also just replace httplib.ssl
with a class providing wrap_socket
. Using functools.partial
makes it very elegant to write this:
import httplib
import ssl
from functools import partial
class fake_ssl:
wrap_socket = partial(ssl.wrap_socket, ssl_version=ssl.PROTOCOL_SSLv3)
httplib.ssl = fake_ssl
这篇关于Python httplib SSL23_GET_SERVER_HELLO:未知协议的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!