如何将新的 SSL 证书和密钥注入正在运行的 Node http.Server?

Posted

技术标签:

【中文标题】如何将新的 SSL 证书和密钥注入正在运行的 Node http.Server?【英文标题】:How can I inject a new SSL cert and key into a running Node http.Server? 【发布时间】:2017-11-20 23:39:32 【问题描述】:

我正在为 TCP 服务运行一个安全的 websocket 代理。这使用标准的http.Server 设置,如:

var webserver = http.createServer(                                                                          
                                                                                                           
        key: fs.readFileSync(srv.ssl_key),                                                                  
        cert: fs.readFileSync(srv.ssl_cert),                                                                
    ,                                                                                                      
    function(request, response)                                                                            
        response.writeHead(404);                                                                            
        response.end();                                                                                     
    ,                                                                                                      
    function(err)                                                                                          
        srv.log(err);                                                                                       
                                                                                                           
);

如您所见,我们已经在使用hilariously undocumented facilities:http.createServer() 的选项和错误处理程序参数。

SSL 密钥和证书由 LetsEncrypt certbot 定期重新生成。发生这种情况时,我想将新密钥和证书注入网络服务器,而无需重新生成新密钥或重新初始化我的 websocket。

还有哪些无证设施可以让我这样做?

【问题讨论】:

【参考方案1】:

使用 SNICallback

实际上,您不应该提供certkey,而是使用SNICallback 代替它们。

(HTTPS 实际上只是 HTTP 和 TLS 的封装,因此通常最好直接查看 TLS 文档以了解有关证书的任何内容)

例如:

function getCerts(servername, cb) 
  cb(null, tls.createSecureContext(
    key: '...' // privkey.pem
  , cert: '...' // cert.pem + '\\r\\n' + chain.pem
  ));


http.createServer( SNICallback: getCerts );

请务必注意,错误会被吞并并导致浏览器 tls 连接错误。如果您遇到错误情况,我强烈建议您在cb(err) 之前先console.error(err),因为没有办法捕获它或知道它是什么类型的错误。这是节点团队有意做出的决定。

Greenlock 会为你做这件事

这正是我对我编写的 ssl 证书管理器所做的事情,Greenlock.js 和 Greenlock for Express.js,它将:

自动配置 SSL 动态地用于您允许的任何域 自动续订过期证书 热加载较新的证书 存储插件可以处理自定义逻辑,因为它在发布或更新之前运行

它通过 ACME / Let's Encrypt 自动颁发证书,但是,如果您需要更自定义的解决方案,您可以覆盖默认存储插件以始终返回证书,然后它甚至永远不会访问 ACME API。

【讨论】:

【参考方案2】:

你必须:

    webserver.close()关闭当前的网络服务器 使用您的新密钥和证书创建一个新的网络服务器实例(上面有一个.setOptions() 方法,您可能认为可以使用它来更改keycert 选项,但是没有办法让它实例化后生成新的 TLS 凭证) 在带有websocketServer.mount(websocketOptions) 的websocket 服务器上安装新的网络服务器,其中websocketOptions.httpServer 是您的新网络服务器实例

这将运行良好且流畅,不会干扰正在运行的连接。

【讨论】:

以上是关于如何将新的 SSL 证书和密钥注入正在运行的 Node http.Server?的主要内容,如果未能解决你的问题,请参考以下文章

Rabbitmq 无需重启即可重新加载/刷新新证书

https如何生成密钥

使用 ssl 证书和带有卷的密钥部署 postgresql docker

SSL 对等证书或 SSH 远程密钥不正确

DTLS协议中的509证书和密钥如何传输

如何从 --capath 获取密钥和证书