【问题标题】:Python httplib SSL23_GET_SERVER_HELLO:unknown protocolPython httplib SSL23_GET_SERVER_HELLO:未知协议
【发布时间】:2013-09-07 03:42:08
【问题描述】:

注意:此代码在 Ubuntu 上运行良好,但在 mac 上却不行

import ssl 
import httplib 
httplib.HTTPConnection(server, port, timeout)

但它会引发错误:

[Errno 1] _ssl.c:503: 错误:140770FC:SSL 例程:SSL23_GET_SERVER_HELLO:未知协议

现在代码不使用 urllib.request 而是使用 httplib

我想更改代码,使其将 SSLv3 作为默认协议,如下所示:

ssl.SSLContext(ssl.PROTOCOL_SSLv3)

我环顾四周,发现链接很少,但没有任何效果!

this link is for ubuntu

link for python urllib and cURL

python bug fix, but again for urllib

【问题讨论】:

    标签: python python-2.7 ssl httplib


    【解决方案1】:

    注意:HTTPSConnection 构造函数允许传递 ssl context 作为参数,因为 python 2.7.9,应该在这种情况下使用。

    此答案早于该更改,因此仅适用于过时的 python 版本。


    httplib.HTTPSConnection.connect 只是在打开的套接字上调用ssl.wrap_socket 来初始化一个https 连接,不幸的是你不能在python2.7 中指定任何参数(python3 允许passing the SSLContext)。

    如果你想指定协议版本,你需要猴子补丁这两个之一:

    方法一:补丁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 进行的所有连接的协议版本。

    方法二:补丁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所有代码的默认协议版本,因此也会影响其他库。

    编辑:

    方法 3:因为 httplib 实际上只从ssl 访问wrap_socket,所以您也可以将httplib.ssl 替换为提供wrap_socket 的类。使用functools.partial 可以非常优雅地编写此代码:

    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
    

    【讨论】:

    • 我尝试了方法 3,现在它抛出“SSL 例程:SSL3_GET_RECORD:wrong version number”,但如果我通过“openssl s_client -connect host:port | grep Protocol”检查服务器协议,它会返回“Protocol : SSLv3"!我会尝试其他方法和lyk..
    • 尝试了所有 3 种方法现在都出现错误(对于所有方法)“SSL 例程:SSL3_GET_RECORD:错误的版本号”
    • 无论您使用上述方法中的哪种方法,结果都应该相同。您是否尝试过不同的协议版本?我不确定如何重现您收到的错误。使用 TLSv1 客户端连接到 SSLv3 服务器时,我只会收到完全相同的错误...
    • 是的,我已经尝试了所有使用 SSLv3 和 TLSv1 的协议,它说“错误的版本号”,使用 SSLv23 它说“未知协议”,而 SSLv2 只是超时。我相信这是我的环境的问题,但您的代码解决了最初的问题。
    猜你喜欢
    • 2023-03-31
    • 1970-01-01
    • 2016-01-11
    • 2014-02-03
    • 2019-03-12
    • 2014-04-22
    • 1970-01-01
    • 2015-11-29
    • 2014-04-23
    相关资源
    最近更新 更多