是否有可能在NodeJS中dynamic返回SSL证书?

我想在我的NodeJS应用程序中dynamic地返回一个ssl证书信息。 我有两个域名链接到相同的节点应用程序。 我只看到SSL服务器创build时可以指定SSL设置。 是否有可能根据请求的urldynamic返回SSL证书?

否则,如果我必须在另一个端口上创build第二个服务器实例,我是否可以透明地将每个请求传送到原始端口? 我可以让它看起来像不在第二个端口上运行吗?

谢谢,杰夫

是的,可以用一台服务器来完成。 但要注意的是,它支持SNI的客户端 – 这是最现代的浏览器。

这是你如何做到的:

//function to pick out the key + certs dynamically based on the domain name function getSecureContext (domain) { return crypto.createCredentials({ key: fs.readFileSync('/path/to/domain.key'), cert: fs.readFileSync('/path/to/domain.crt'), ca: [fs.readFileSync('/path/to/CA_cert_1.crt'), fs.readFileSync('/path/to/CA_cert_2.crt'), <include all CA certs that you have to> ... ] }).context; } //read them into memory var secureContext = { 'domain1': getSecureContext('domain1'), 'domain2': getSecureContext('domain2'), . . } //provide a SNICallback when you create the options for the https server var options = { SNICallback: function (domain) { return secureContext[domain]; }, //SNICallback is passed the domain name, see NodeJS docs on TLS cert: fs.readFileSync('/path/to/server.crt'), key: fs.readFileSync('/path/to/server.key'), } } //create your https server var server = require('https').createServer(options, [requestListener]); //using Express var server = require('https').createServer(options, require('express')()); server.listen(<someport>); 

这是可行的,因为https的选项类似于tls.createServer()。 确保在crypto.createCredentials调用中包含所有必需的CA中间和根证书。 另外,如果你有一个CA包,在使用它们之前将它们拆分成多个单一的crt文件,因为'ca'接受一个证书数组。

crypto.createCredentials()已被弃用,所以请使用tls.createSecureContext()

tls.createServer()在选项中必须具有keycert ,因为它们在手册中是必需的。 也许在不支持SNICallback情况下, tls.createServer()使用这些参数作为默认值。

 var secureContext = { 'mydomain.com': tls.createSecureContext({ key: fs.readFileSync('../path_to_key1.pem', 'utf8'), cert: fs.readFileSync('../path_to_cert1.crt', 'utf8'), ca: fs.readFileSync('../path_to_certificate_authority_bundle.ca-bundle1', 'utf8'), // this ca property is optional }), 'myotherdomain.com': tls.createSecureContext({ key: fs.readFileSync('../path_to_key2.pem', 'utf8'), cert: fs.readFileSync('../path_to_cert2.crt', 'utf8'), ca: fs.readFileSync('../path_to_certificate_authority_bundle.ca-bundle2', 'utf8'), // this ca property is optional }), } try { var options = { SNICallback: function (domain, cb) { if (secureContext[domain]) { if (cb) { cb(null, secureContext[domain]); } else { // compatibility for older versions of node return secureContext[domain]; } } else { throw new Error('No keys/certificates for domain requested'); } }, // must list a default key and cert because required by tls.createServer() key: fs.readFileSync('../path_to_key.pem'), cert: fs.readFileSync('../path_to_cert.crt'), } https.createServer(options, function (req, res) { res.end('Your dynamic SSL server worked!') // Here you can put proxy server routing here to send the request // to the application of your choosing, running on another port. // node-http-proxy is a great npm package for this }).listen(443); } catch (err){ console.error(err.message); console.error(err.stack); } 

在服务器内部,您可以使用nodejs包http-proxy将您的https请求路由到您的各种应用程序。

我只想指出,@clusterfork对我来说是完美的,但系统更新使我的整个解决scheme崩溃,因为现在SNICallback正在处理2个参数,并且系统的一个简单更新使得它全部崩溃。 所以现在它正在恢复工作,因为SNICallback现在带有2个参数,domain&callback和一个简单的代码适应,所以它可以工作,正如@risyasin在评论中所说的那样。