4

我想将 ssl 支持添加到基于 SocketServer.TCPServer 类的现有 TCP 服务器。所以我覆盖了 TCPServer 类的默认构造函数并添加了 ssl.wrap_socket(...)-call:

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 连接:)

4

3 回答 3

9

握手被阻塞,因为您在绑定后包装了套接字;套接字正在侦听新连接,还没有客户端接受您的连接。

在接受连接时包装套接字:

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)

现在握手成功了,因为对方有客户要握手。

流处理程序不需要额外的工作;pythonssl库为您提供具有与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)
于 2013-09-20T15:49:53.957 回答
3

好的,我找到了解决方案。现在我使用 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 的设置方法中:

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

这似乎工作正常:-)

于 2011-05-17T16:47:27.970 回答
0

那是因为您必须do_handshake_on_connect在调用 ssl.wrap_socket 时设置参数:

参数 do_handshake_on_connect 指定是否在执行 socket.connect() 后自动进行 SSL 握手,或者应用程序是否会通过调用 SSLSocket.do_handshake() 方法显式调用它。调用 SSLSocket.do_handshake() 显式地让程序控制握手中涉及的套接字 I/O 的阻塞行为。

来源:http ://docs.python.org/library/ssl.html

于 2011-05-14T12:12:22.997 回答