TCP-Server over SSL using SocketServer.TCPServer

我怕爱的太早我们不能终老 提交于 2019-12-04 13:25:43

问题


i want to add ssl-support to an existing TCP-server which is based on the SocketServer.TCPServer class. So i overrode the default constructor of the TCPServer class and added the 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()

When starting the server, no error occurrs. So i modified my simple test-client to support ssl, too:

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:

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. Does anyone knows how to fix the problem? I simply want to use an encrypted TCP-connection :)


回答1:


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().

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)



回答2:


Ok, i found a solution. Now i use something similar to this using the OpenSSL-package:

Inside the 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:

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




回答3:


That's because you have to set the do_handshake_on_connect argument in your call to ssl.wrap_socket:

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. Calling SSLSocket.do_handshake() explicitly gives the program control over the blocking behavior of the socket I/O involved in the handshake.

Source: http://docs.python.org/library/ssl.html



来源:https://stackoverflow.com/questions/6001644/tcp-server-over-ssl-using-socketserver-tcpserver

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!