簡體   English   中英

使用SocketServer.TCPServer通過SSL的TCP-Server

[英]TCP-Server over SSL using SocketServer.TCPServer

我想將ssl-support添加到基於SocketServer.TCPServer類的現有TCP服務器。 所以我覆蓋了TCPServer類的默認構造函數並添加了ssl.wrap_socket(...) - 調用:

class MyTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
    def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True):
        # See SocketServer.TCPServer.__init__
        # (added ssl-support):
        SocketServer.BaseServer.__init__(self, server_address,
                                                        RequestHandlerClass)
        self.socket = ssl.wrap_socket(
                    socket.socket(self.address_family, self.socket_type),
                    server_side=True,
                    certfile='cert.pem'
                    )

        if bind_and_activate:
            self.server_bind()
            self.server_activate()

啟動服務器時,不會發生錯誤。 所以我修改了我的簡單測試客戶端以支持ssl:

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock = ssl.wrap_socket(s)
sock.connect(('192.168.1.1', 54321))

同樣沒有錯誤發生,但連接調用阻塞。 使用Ctrl + C關閉客戶端時,它顯示以下內容:

Traceback (most recent call last):
  File "exampleClient.py", line 10, in <module>
    sock.do_handshake()
  File "/usr/lib/python2.6/ssl.py", line 293, in do_handshake
    self._sslobj.do_handshake()
KeyboardInterrupt

所以do_handshake在連接時會阻塞。 有誰知道如何解決這個問題? 我只是想使用加密的TCP連接:)

握手是阻塞的,因為你在綁定后包裝套接字; 套接字正在偵聽新連接,沒有客戶端尚未接受您的連接。

改為在接受連接時包裹套接字:

class MyTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
    def get_request(self):
        (socket, addr) = SocketServer.TCPServer.get_request(self)
        return (ssl.wrap_socket(socket, server_side=True, certfile="cert.pem"),
                addr)

現在握手成功,因為有對對方握手的客戶端。

流處理程序不需要額外的工作; python ssl庫為您提供與socket.socket()具有相同接口的對象。

您也可以盡早包裝套接字,但是在您接受連接之前推遲握手:

class MyTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
    def server_bind(self):
        SocketServer.TCPServer.server_bind(self)
        self.socket = ssl.wrap_socket(
            self.socket, server_side=True, certfile="cert.pem",
            do_handshake_on_connect=False)

    def get_request(self):
        (socket, addr) = SocketServer.TCPServer.get_request(self)
        socket.do_handshake()
        return (socket, addr)

好的,我找到了解決方案。 現在我用類似的東西來使用OpenSSL的包:

在MyTCPServer-Constructor中:

SocketServer.BaseServer.__init__(self, server_address, RequestHandlerClass)
ctx = SSL.Context(SSL.SSLv23_METHOD)
cert = 'cert.pem'
ctx.use_privatekey_file(cert)
ctx.use_certificate_file(cert)
self.socket = SSL.Connection(ctx, socket.socket(self.address_family,
                                                        self.socket_type))
if bind_and_activate:
    self.server_bind()
    self.server_activate()

在StreamRequestHandler的setup-method中:

self.connection = self.request
self.rfile = socket._fileobject(self.request, "rb", self.rbufsize)
self.wfile = socket._fileobject(self.request, "wb", self.wbufsize)

這似乎工作正常:-)

那是因為你必須在調用ssl.wrap_socket時設置do_handshake_on_connect參數:

參數do_handshake_on_connect指定在執行socket.connect()之后是否自動執行SSL握手,或者應用程序是否通過調用SSLSocket.do_handshake()方法顯式調用它。 調用SSLSocket.do_handshake()顯式地讓程序控制握手中涉及的套接字I / O的阻塞行為。

資料來源: http//docs.python.org/library/ssl.html

暫無
暫無

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

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