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. So I redefined the default constructor of the TCPServer class and added 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, an error does not occur. Therefore, I modified my simple test client to support ssl:

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

Again, the error does not occur, but the call connection is blocked. 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 

Thus, do_handshake is blocked when connected. Does anyone know how to solve a problem? I just want to use an encrypted TCP connection :)

+4
source share
3 answers

Ok, I found a solution. Now I am using something similar to this using the OpenSSL package:

Inside 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 installation method of StreamRequestHandler:

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

This works fine :-)

+3
source

The handshake is blocked because you reassure the socket after binding; the socket listens for new connections until the client accepts your connections.

Exchange the socket when you accept the connection:

 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 is succeeding because there is a customer on the other side to shake hands.

The stream handler does not require additional work; python ssl library provides you objects with the same interface as socket.socket() .

You can also wrap the socket first, but put off the handshake until you accept the 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) 
+6
source

This is because you must set the do_handshake_on_connect argument in your ssl.wrap_socket call:

The do_handshake_on_connect parameter specifies whether to do SSL handshake automatically after socket.connect () is executed, or whether the application will call it explicitly by calling the SSLSocket.do_handshake () method. Calling SSLSocket.do_handshake () explicitly gives programmatic control over the blocking behavior of the I / O socket involved in the handshake.

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

0
source

All Articles