" ssl"的文档Python 2.7.9标准库中的模块说:
如果将此模块用作多处理应用程序的一部分(例如使用multiprocessing或concurrent.futures模块),请注意OpenSSL的内部随机数生成器无法正确处理分叉进程。如果应用程序使用os.fork()的任何SSL功能,则应用程序必须更改父进程的PRNG状态。任何成功调用RAND_add(),RAND_bytes()或RAND_pseudo_bytes()就足够了。
具体而言,它究竟意味着什么?我应该在每个fork之后在主进程中调用这三个函数中的一个吗?
此外,这是否适用于多个线程?
如果相关,我有一个在Gunicorn服务器上运行的Django应用程序。主进程不会对SSL做任何事情,但工作人员会这样做。
答案 0 :(得分:1)
具体来说它究竟意味着什么?
我相信细节在#18747。
主要风险是每个孩子都会获得PRNG州的副本。如果你在两个孩子之间没有接触到PRNG,他们可能会得到相同的PRNG状态,可能会允许预测攻击。 NIST的CVE 2013-1900描述了针对Postgres的等效攻击向量,因为"生成的随机数不够,这可能允许远程认证用户产生未指定的影响"。不是那么具体......
主进程不会对SSL做任何事情,但是工作人员会这样做。
嗯,问题是两个叉子之间没有做任何SSL的事情,所以从来没有用SSL做任何事情保证......
除非你绝对确定你从未初始化 SSL,否则孩子们会在他们第一次需要时为自己初始化(并播种)SSL。我不确定一个好方法来说服自己这种情况正在发生,但它可能值得尝试。 (也许在启动时使用monkeypatch SSL,然后在fork之后取消它,所以如果你间接触摸它,一切都会死掉?)
我应该在每个fork之后在主进程中调用这三个函数中的一个吗?
我会谨慎一点。这难以做到,还是效率问题?
如果遇到困难,你可以随时在每个孩子的开头种下RNG。 * 对于传统的prefork服务器,它为每个连接启动一个worker ,这可能是灾难性的低效率,但我非常确定gunicorn doesn't work that way。它在启动时创建了一个工作池(我认为默认为2 * NCPU + 1),也许它偶尔会回收它们,但是新客户要么等待一个自由工作者(在同步模型中),要么进入一个工作人员。 s gevent / asyncio / thread / etc.池(在各种异步模型中)。因此,孩子的创业时间成本应该是无关紧要的。 (如果我错了,请忽略这个猜测 - 或者更好,纠正我的无知......)
此外,这是否适用于多个线程?
不,线程将(可变)共享相同的RNG状态,而不是获得它的副本,因此您在那里安全。 (当然,这也适用于gunicorn / gevent微线程。)
*我最初建议或取消初始化OpenSSL并重新初始化它,结果证明,如果你这样做,至少如果主服务器或服务器中有线程,一切都会变成地狱。所以不要这样做,只是种子。