我想在我的NodeJS應用程序中動態地返回一個ssl證書信息。我有兩個域名鏈接到相同的節點應用程序。我只看到可以在創建服務器時指定ssl設置。是否有可能根據請求的url動態返回SSL證書?否則,如果我必須改爲在另一個端口上創建第二個服務器實例,我將能夠透明地將每個請求傳送到原始端口嗎?我能否讓它看起來像沒有在第二個端口上運行?是否有可能在NodeJS中動態返回SSL證書?
感謝, 傑夫
我想在我的NodeJS應用程序中動態地返回一個ssl證書信息。我有兩個域名鏈接到相同的節點應用程序。我只看到可以在創建服務器時指定ssl設置。是否有可能根據請求的url動態返回SSL證書?否則,如果我必須改爲在另一個端口上創建第二個服務器實例,我將能夠透明地將每個請求傳送到原始端口嗎?我能否讓它看起來像沒有在第二個端口上運行?是否有可能在NodeJS中動態返回SSL證書?
感謝, 傑夫
是的,這是可能的一個服務器做。但需要注意的是,它可以支持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>);
這工作,因爲the options for https類似於tls.createServer()。確保在crypto.createCredentials調用中包含所有必需的CA中間和根證書。另外,如果你有一個CA包,在使用它們之前將它們拆分成多個單一的crt文件,因爲'ca'接受一組證書。
不錯!每個SSL證書都需要有專門的IP嗎?我想在同一臺服務器上使用SSL託管多個域。當他們購買他們的網站時,我們會使用API爲他們自動購買SSL證書和域名。如果我可以在具有相同IP的同一臺服務器上運行多個域,那將會很棒,但是感覺每個證書都需要一個專用IP,但不太確定。 – Keverw
,我希望可以動態刪除/添加網站。構建一個SaaS應用程序或至少想要這部分應該是我們需要儘早弄清楚的。看完維基百科頁面後,看起來我們不需要專用IP。所以這是一個優點,但是getSecureContext是在請求時或服務器啓動時調用的?因爲每當站點獲得SSL證書請求時,getSecureContext就可以在數據庫中查找。哼。試圖思考這應該如何工作。 – Keverw
,並想知道它會在不支持它的舊瀏覽器上做什麼。給他們證書錯誤,我承擔? – Keverw
crypto.createCredentials()
已棄用,所以請改用tls.createSecureContext()
。
tls.createServer()必須在選項key
和cert
,因爲他們都在手冊中要求的。也許tls.createServer()
使用這些參數作爲默認值,以防SNICallback
不支持。
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對我來說是完美的,但系統更新使我的整個解決方案崩潰,因爲現在SNICallback使用2個參數,並且系統的一個簡單更新使它全部崩潰。所以現在它正在恢復工作,因爲SNICallback現在帶有2個參數,域名爲&回調,並且一個簡單的代碼適應使它可以工作,正如@risyasin在評論中所說的那樣。
我想這也是一個答案。我打算構建一個Node.js應用程序,它可以託管多個域,每個域都有一個SSL證書。如果我們可以將SSL證書信息存儲在數據庫中,這將非常有用。因此,一旦我們檢測到他們來自的域名,我們就可以提供他們的網站主題和內容。我知道Node.js有一種方法可以在啓動時定義一個SSL證書,但不知道如何根據它們所在的域來動態執行SSL證書。 – Keverw
不確定,但不會https://github.com/nodejitsu/node-http-proxy有幫助嗎? –