簡體   English   中英

如何處理原始 Python 套接字中的 ssl 連接?

[英]How to handle ssl connections in raw Python socket?

我正在編寫一個程序來下載給定的網頁。 由於某些限制,我只需要對所有連接使用原始 python 套接字。 所以我建立一個到給定域(對象響應頭中的 Host 字段)的套接字連接,然后在這個域上發送 GET 請求。 現在,當 url 是 https url 時,我想我需要先進行 SSL 握手(否則我會從服務器收到非 200 OK 響應和其他提及 P3P 策略的錯誤響應)。 我檢查了 curl 的響應以檢查它如何能夠成功下載,而我卻沒有,結果 curl 首先執行 SSL 握手(這就是所有不同之處)。 curl 總是能夠成功下載給定的對象,唯一的區別總是它所做的 SSL 握手。

所以我想知道如何在原始 python 套接字中進行 SSL 握手? 基本上我想要一個簡單的解決方案,除了使用原始套接字之外,它允許我做最少的事情。

下面是一個帶有 SLL 的 TCP 客戶端示例。

不確定這是否是下載網頁的最佳方式,但它應該回答您的問題“原始 python 套接字中的 SSL 握手”。

您可能需要調整 struct.pack/unpack 但您會得到大致的想法:

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

然后你像這樣使用這個類:

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

您可以使用 python ssl 模塊的 wrap_socket 方法將您的套接字轉換為一個可以使用 SSL 的套接字。 完成此操作后,您可以像往常一樣使用它,但在內部數據將為您加密和解密。 這些是該方法的文檔: https : //docs.python.org/2/library/ssl.html#ssl.wrap_socket

我認為更簡單的方法是使用 SSL 上下文並包裝 TCP 套接字。

Python SSL 模塊的文檔通過示例給出了非常詳盡的解釋。 我建議您閱讀Python 2Python 3 ssl 模塊文檔的相關部分。 實現你想要的應該很容易。

希望這可以幫助!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM