Python httplib SSL23_GET_SERVER_HELLO:unknown protocol

后端 未结 1 493
闹比i
闹比i 2020-12-19 10:44

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.

相关标签:
1条回答
  • 2020-12-19 11:24

    Note: The HTTPSConnection constructor allows to pass an ssl context as argument since python 2.7.9, which should be used in this case.

    This answer predates that change and therefore only applies to outdated versions of python.


    httplib.HTTPSConnection.connect just calls ssl.wrap_socket on the opened socket to initalize a https connection, unfortunately you can't specify any parameters in python2.7 (python3 allows passing the SSLContext).

    If you want to specify the protocol version, you'd need to monkey patch one of these two:

    Method 1: patch 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
    

    This changes the protocol version for all connections made with HTTPSConnection.

    Method 2: patch 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
    

    This changes the default protocol version for all code that uses wrap_socket, therefore also affects other libraries.

    edit:

    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
    
    0 讨论(0)
提交回复
热议问题