我想将ssl-support添加到基于SocketServer.TCPServer类的现有TCP服务器。 所以我覆盖了TCPServer类的默认构造函数并添加了ssl.wrap_socket(...) - 调用:
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()
启动服务器时,不会发生错误。 所以我修改了我的简单测试客户端以支持ssl:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock = ssl.wrap_socket(s)
sock.connect(('192.168.1.1', 54321))
同样没有错误发生,但是connect-call是阻塞的。使用Ctrl + C关闭客户端时,它显示以下内容:
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
所以do_handshake在连接时会阻塞。有谁知道如何解决这个问题?我只想使用加密的TCP连接:)
答案 0 :(得分:8)
握手是阻塞的,因为在绑定之后你正在包装套接字;套接字正在侦听新连接,但客户端尚未接受您的连接。
在接受连接时包裹套接字:
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)
现在握手成功,因为另一方有一个客户端用握手。
流处理程序不需要额外的工作; python ssl
库为您提供与socket.socket()
具有相同接口的对象。
你也可以提前包装套接字,但是在你接受连接之前推迟握手:
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)
答案 1 :(得分:3)
好的,我找到了解决方案。现在我使用类似的东西 this使用OpenSSL包:
在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()
在StreamRequestHandler的setup-method中:
self.connection = self.request
self.rfile = socket._fileobject(self.request, "rb", self.rbufsize)
self.wfile = socket._fileobject(self.request, "wb", self.wbufsize)
这似乎工作正常: - )
答案 2 :(得分:0)
那是因为你必须在调用ssl.wrap_socket时设置do_handshake_on_connect
参数:
参数do_handshake_on_connect 指定是否执行SSL 做完后自动握手 socket.connect(),或者是否 应用程序会调用它 明确地,通过调用 SSLSocket.do_handshake()方法。 调用SSLSocket.do_handshake() 明确给出程序控制 关于阻止行为 握手中涉及的套接字I / O.