How to handle ssl connections in raw Python socket?

前端 未结 3 1997
执念已碎
执念已碎 2021-01-28 00:53

I\'m writing a program to download a given webpage. I need to only use raw python sockets for all the connection due to some restriction. So I make a socket connection to a give

3条回答
  •  天命终不由人
    2021-01-28 01:17

    Here is an example of a TCP client with SLL.

    Not sure if it's the best way to download a web page but it should answer your question "SSL handshake in raw python socket".

    You will probably have to adapt the struct.pack/unpack but you get the general idea:

    import socket
    import ssl
    import struct
    import binascii
    import sys
    
    class NotConnectedException(Exception):
        def __init__(self, message=None, node=None):
            self.message = message
            self.node = node
    
    class DisconnectedException(Exception):
        def __init__(self, message=None, node=None):
            self.message = message
            self.node = node
    
    class Connector:
        def __init__(self):
            pass
    
        def is_connected(self):
            return (self.sock and self.ssl_sock)
    
        def open(self, hostname, port, cacert):
            self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.ssl_sock = ssl.wrap_socket(self.sock, ca_certs=cacert, cert_reqs=ssl.CERT_REQUIRED)
    
            if hostname == socket.gethostname():
                ipaddress = socket.gethostbyname_ex(hostname)[2][0]
                self.ssl_sock.connect((ipaddress, port))
            else:
                self.ssl_sock.connect((hostname, port))
    
            self.sock.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 1)
    
        def close(self):
            if self.sock: self.sock.close()
            self.sock = None
            self.ssl_sock = None
    
        def send(self, buffer):
            if not self.ssl_sock: raise NotConnectedException("Not connected (SSL Socket is null)")
            self.ssl_sock.sendall(struct.pack('L', len(buffer)))
            self.ssl_sock.sendall(buffer)
    
        def receive(self):
            if not self.ssl_sock: raise NotConnectedException("Not connected (SSL Socket is null)")
            data_size_buffer = self.ssl_sock.recv(4)
    
            if len(data_size_buffer) <= 0:
                raise DisconnectedException()
    
            data_size = struct.unpack('L', data_size_buffer)[0]
            received_size = 0
            data_buffer = ""
    
            while received_size < data_size:
                chunk = self.ssl_sock.recv(1024)
                data_buffer += chunk
                received_size += len(chunk)
    
            return data_buffer
    

    Then you use the class like this:

        connector = Connector.Connector()
        connector.open(server_ip, server_port, path_to_the_CA_cert.pem)
        connector.send(your_data)
        response = connector.receive()
        connector.close()
    

提交回复
热议问题