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

Big*_*gie 4 python ssl tcp socketserver

我想将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()
Run Code Online (Sandbox Code Playgroud)

启动服务器时,不会发生错误.所以我修改了我的简单测试客户端以支持ssl:

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock = ssl.wrap_socket(s)
sock.connect(('192.168.1.1', 54321))
Run Code Online (Sandbox Code Playgroud)

同样没有错误发生,但连接调用阻塞.使用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
Run Code Online (Sandbox Code Playgroud)

所以do_handshake在连接时会阻塞.有谁知道如何解决这个问题?我只是想使用加密的TCP连接:)

Mar*_*ers 8

握手是阻塞的,因为你在绑定后包装套接字; 套接字正在侦听新连接,没有客户端尚未接受您的连接.

改为在接受连接时包裹套接字:

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)
Run Code Online (Sandbox Code Playgroud)

现在握手成功,因为没有对对方握手客户端.

流处理程序不需要额外的工作; 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)
Run Code Online (Sandbox Code Playgroud)