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