【问题标题】:Adding SSL Support to SocketServer向 SocketServer 添加 SSL 支持
【发布时间】:2011-12-20 22:25:26
【问题描述】:

我有一个基于ThreadingTCPServer 的服务器。现在我想为该服务器添加 SSL 支持。 如果没有 SSL,它可以正常工作,但使用 SSLv3 我无法将客户端连接到服务器,它总是会引发异常:Error 111 Connection Refused。错误表示该端口上没有 SSL 服务器。

我根据在 Stackoverflow 找到的示例添加了 SSL 支持。 这是我的代码:

服务器:

class BeastServer(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 = 'server.pem'
        key = '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_a

客户:

class Client(object) :

    def verbinden (self, ip_) :

        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        ssl_sock = ssl.wrap_socket(s, cert_reqs=ssl.CERT_REQUIRED,
                    ssl_version=ssl.PROTOCOL_SSLv3, ca_certs='server.pem')
        ssl_sock.connect((ip_, 10012))

        return ssl_sock

密钥和证书文件是使用开放 SSL 创建的。 我希望有人能告诉我问题是什么。

感谢您的帮助

向帕特里克致敬

【问题讨论】:

    标签: python ssl socketserver


    【解决方案1】:

    只使用标准库

    服务器端:

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

    客户端:

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

    效果很好

    【讨论】:

      【解决方案2】:

      事实上,标准库中的 ssl 可以正常工作,也许初始代码的问题是您没有要求基类不要绑定和激活。请参见下面基于 TCPServer 的工作示例。证书和密钥文件应位于同一目录中。

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

      【讨论】:

        【解决方案3】:

        安装openssl

        sudo aptitude install python-openssl

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-10-30
          • 2011-03-10
          • 1970-01-01
          相关资源
          最近更新 更多