简体   繁体   English

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

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

i want to add ssl-support to an existing TCP-server which is based on the SocketServer.TCPServer class. 我想将ssl-support添加到基于SocketServer.TCPServer类的现有TCP服务器。 So i overrode the default constructor of the TCPServer class and added the ssl.wrap_socket(...)-call: 所以我覆盖了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()

When starting the server, no error occurrs. 启动服务器时,不会发生错误。 So i modified my simple test-client to support ssl, too: 所以我修改了我的简单测试客户端以支持ssl:

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

Again no error occurrs, but the connect-call is blocking. 同样没有错误发生,但连接调用阻塞。 When closing the client using Ctrl+C it shows the following: 使用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

So the do_handshake is blocking when connecting. 所以do_handshake在连接时会阻塞。 Does anyone knows how to fix the problem? 有谁知道如何解决这个问题? I simply want to use an encrypted TCP-connection :) 我只是想使用加密的TCP连接:)

The handshake is blocking because you are wrapping the socket after binding ; 握手是阻塞的,因为你在绑定后包装套接字; the socket is listening for new connections, there is no client yet to accept your connections. 套接字正在侦听新连接,没有客户端尚未接受您的连接。

Wrap the socket when accepting a connection instead: 改为在接受连接时包裹套接字:

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)

Now the handshake succeeds because there is a client on the other side to shake hands with . 现在握手成功,因为有对对方握手的客户端。

There is no additional work necessary for the stream handler; 流处理程序不需要额外的工作; the python ssl library gives you objects with the same interface as socket.socket() . python ssl库为您提供与socket.socket()具有相同接口的对象。

You can also wrap the socket early, but do postpone the handshake until you accept a connection: 您也可以尽早包装套接字,但是在您接受连接之前推迟握手:

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)

Ok, i found a solution. 好的,我找到了解决方案。 Now i use something similar to this using the OpenSSL-package: 现在我用类似的东西来使用OpenSSL的包:

Inside the MyTCPServer-Constructor: 在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()

And in the setup-method of the StreamRequestHandler: 在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)

This seems to work fine :-) 这似乎工作正常:-)

That's because you have to set the do_handshake_on_connect argument in your call to ssl.wrap_socket: 那是因为你必须在调用ssl.wrap_socket时设置do_handshake_on_connect参数:

The parameter do_handshake_on_connect specifies whether to do the SSL handshake automatically after doing a socket.connect(), or whether the application program will call it explicitly, by invoking the SSLSocket.do_handshake() method. 参数do_handshake_on_connect指定在执行socket.connect()之后是否自动执行SSL握手,或者应用程序是否通过调用SSLSocket.do_handshake()方法显式调用它。 Calling SSLSocket.do_handshake() explicitly gives the program control over the blocking behavior of the socket I/O involved in the handshake. 调用SSLSocket.do_handshake()显式地让程序控制握手中涉及的套接字I / O的阻塞行为。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM