use*_*648 3 ssl gevent python-2.7
每次客户端连接到服务器时,我都会收到提示输入PEM密码短语.我想只在服务器启动时输入它,而不必再次输入它.Twisted Matrix框架只需要启动时的密码短语,为什么不gevent?或者我使用gevent错了?如果我使用不需要PEM密码的证书,下面的代码工作正常,但我想使用带密码短语的证书.
from gevent.server import StreamServer
from gevent.pool import Pool
from gevent import monkey
class SocketPool(object):
def __init__(self): self.pool = Pool(1000)
def listen(self, socket):
while True:
line = socket.recv(1024)
if not line: break
print line
socket.close()
break
def add_handler(self, socket, address):
print "connection made:", address
if self.pool.full(): raise Exception("At maximum pool size")
else: self.pool.spawn(self.listen, socket)
def shutdown(self): self.pool.kill()
monkey.patch_all()
sockPool = SocketPool()
server = StreamServer(('', 5000), sockPool.add_handler, keyfile='key.pem', certfile='cert.pem')
server.serve_forever()
Run Code Online (Sandbox Code Playgroud)
似乎没有一种简单的方法来解决这个问题在python 2.7上.在内部,gevent.server使用ssl从C调用OpenSSL库的python 模块.该_ssl.sslwrap()函数为每个调用创建一个新的SSLContext,这就是每次建立连接时提示您输入密钥密码的原因.
Twisted使用pyOpenSSL而不是ssl模块.在pyOpenSSL中,首先创建SSLContext,并在每次建立连接时使用该单个上下文.因此,只有在使用Twisted时才会提示您输入密码.
Python 3.2添加了一个带有方法的ssl.SSLContext类wrap_socket().如果您使用的是此版本或更高版本,则可以修改gevent代码以使其更像Twisted,即使用单个SSLContext并将调用替换_ssl.sslwrap()为对wrap_socket()方法的调用.但是,gevent并没有被移植到python3.
您可以通过在前面放置一个SSL代理来卸载gevent的SSL处理,这样到公共端口的传入SSL连接就会在未加密的内部端口上代理到您的gevent服务器.您可以使用Twisted编写自己的代理或使用像stunnel这样的专用代理.但是,这可能会否定您首先想要使用gevent的部分或全部原因.
您可以修改_ssl模块以缓存SSLContexts或使用其他方式接受密码短语. _ssl在python 2.7中使用默认的密码短语回调,它以交互方式提示输入密码短语.这不会那么困难,但它要求您至少知道一点C,python C API和OpenSSL API,而且您必须在部署的任何地方构建和覆盖模块.
您可以使用自己的代码修补gevent以使用SSL包装套接字.这可以完全在python中使用像pyOpenSSL这样的库来完成,但是正确的做法可能是相当多的工作.
最后,您可以使用未加密的密钥.将密钥放在RAM磁盘或加密文件系统(或两者)上可能会满足您的安全要求.