如何将新的 SSL 证书和密钥注入 运行 节点 http.Server?
How can I inject a new SSL cert and key into a running Node http.Server?
我是 运行 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 定期重新生成。发生这种情况时,我想将新密钥和证书注入网络服务器,而不必重新生成新密钥和证书或重新初始化我的网络套接字。
还有什么未记录的设施可以让我这样做?
你必须:
- 关闭当前网络服务器
webserver.close()
- 使用您的新密钥和证书创建一个新的网络服务器实例(上面有一个
.setOptions()
方法,您可能认为您可以使用它来更改 key
和 cert
选项,但无法让它在实例化后生成新的 TLS 凭据)
- 使用
websocketServer.mount(websocketOptions)
在 websocket 服务器上安装新的网络服务器,其中 websocketOptions.httpServer
是您的新网络服务器实例
这将工作得很好而且很顺利,不会干扰 运行 连接。
使用 SNICallback
实际上,您不应该提供 cert
和 key
,而应使用 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 and Greenlock for Express.js,它将:
- 自动配置 SSL
- 对于您允许的任何域都是动态的
- 自动更新即将到期的证书
- 热加载较新的证书
- 存储插件可以处理自定义逻辑,因为它在发行或更新之前运行
它通过 ACME / Let's Encrypt 自动颁发证书,但是,如果您需要更自定义的解决方案,您可以覆盖默认存储插件以始终 return 证书,然后它甚至永远不会命中 ACME API.
我是 运行 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 定期重新生成。发生这种情况时,我想将新密钥和证书注入网络服务器,而不必重新生成新密钥和证书或重新初始化我的网络套接字。
还有什么未记录的设施可以让我这样做?
你必须:
- 关闭当前网络服务器
webserver.close()
- 使用您的新密钥和证书创建一个新的网络服务器实例(上面有一个
.setOptions()
方法,您可能认为您可以使用它来更改key
和cert
选项,但无法让它在实例化后生成新的 TLS 凭据) - 使用
websocketServer.mount(websocketOptions)
在 websocket 服务器上安装新的网络服务器,其中websocketOptions.httpServer
是您的新网络服务器实例
这将工作得很好而且很顺利,不会干扰 运行 连接。
使用 SNICallback
实际上,您不应该提供 cert
和 key
,而应使用 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 and Greenlock for Express.js,它将:
- 自动配置 SSL
- 对于您允许的任何域都是动态的
- 自动更新即将到期的证书
- 热加载较新的证书
- 存储插件可以处理自定义逻辑,因为它在发行或更新之前运行
它通过 ACME / Let's Encrypt 自动颁发证书,但是,如果您需要更自定义的解决方案,您可以覆盖默认存储插件以始终 return 证书,然后它甚至永远不会命中 ACME API.