I have a Server based on ThreadingTCPServer
. Now Ii want to add SSL Support to that Server.
Without SSL it works fine but with SSLv3 I cant connect a Client to
from OpenSSL import SSL
import socket, SocketServer
class SSlSocketServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True):
SocketServer.BaseServer.__init__(self, server_address,
RequestHandlerClass)
ctx = SSL.Context(SSL.SSLv3_METHOD)
cert = 'cert.pem'
key = 'private_key.pem'
ctx.use_privatekey_file(key)
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()
def shutdown_request(self,request):
request.shutdown()
class Decoder(SocketServer.StreamRequestHandler):
def setup(self):
self.connection = self.request
self.rfile = socket._fileobject(self.request, "rb", self.rbufsize)
self.wfile = socket._fileobject(self.request, "wb", self.wbufsize)
def handle(self):
try:
socket1 = self.connection
str1 = socket1.recv(4096)
print str1
except Exception, e:
print 'socket error',e
def main():
server = SSlSocketServer(('127.0.0.1', 9999), Decoder)
server.serve_forever()
if __name__ == '__main__':
main()
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('localhost', 9999))
sslSocket = socket.ssl(s)
print repr(sslSocket.server())
print repr(sslSocket.issuer())
sslSocket.write('Hello secure socket\n')
s.close()
In fact ssl from the standard library works ok, maybe the problem with the initial code was that you were not asking the base class not to bind and activate. See below working example based on TCPServer. Certificate and Key files are expected to be in the same directory.
import os
import SocketServer
class SSLTCPServer(SocketServer.TCPServer):
def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True):
"""Constructor. May be extended, do not override."""
SocketServer.TCPServer.__init__(self, server_address, RequestHandlerClass, False)
dir = os.path.dirname(__file__)
key_file = os.path.join(dir, 'server.key')
cert_file = os.path.join(dir, 'server.crt')
import ssl
self.socket = ssl.wrap_socket(self.socket, keyfile=key_file, certfile=cert_file, cert_reqs=ssl.CERT_NONE)
if bind_and_activate:
self.server_bind()
self.server_activate()
Only use the standard library
Server side :
from SocketServer import TCPServer, ThreadingMixIn, StreamRequestHandler
import ssl
class MySSL_TCPServer(TCPServer):
def __init__(self,
server_address,
RequestHandlerClass,
certfile,
keyfile,
ssl_version=ssl.PROTOCOL_TLSv1,
bind_and_activate=True):
TCPServer.__init__(self, server_address, RequestHandlerClass, bind_and_activate)
self.certfile = certfile
self.keyfile = keyfile
self.ssl_version = ssl_version
def get_request(self):
newsocket, fromaddr = self.socket.accept()
connstream = ssl.wrap_socket(newsocket,
server_side=True,
certfile = self.certfile,
keyfile = self.keyfile,
ssl_version = self.ssl_version)
return connstream, fromaddr
class MySSL_ThreadingTCPServer(ThreadingMixIn, MySSL_TCPServer): pass
class testHandler(StreamRequestHandler):
def handle(self):
data = self.connection.recv(4096)
self.wfile.write(data)
#test code
MySSL_ThreadingTCPServer(('127.0.0.1',5151),testHandler,"cert.pem","key.pem").serve_forever()
Client side :
import os
import socket, ssl
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
ssl_sock = ssl.wrap_socket(s,
ca_certs="cert.pem",
cert_reqs=ssl.CERT_REQUIRED,
ssl_version=ssl.PROTOCOL_TLSv1)
ssl_sock.connect(('127.0.0.1',5151))
ssl_sock.send('hello ~MySSL !')
print ssl_sock.recv(4096)
ssl_sock.close()
works well