I'm implementing https server in nodejs which should be accessible as from local IP address as from public IP address over SSL. With help of documentation (and some answers here on SO) I found how I can dynamically provide different Certificate for different hostnames (using SNICallback) but as documentation points that SNICallback works only with hostnames and not with IPs:
Currently, the only server names supported are DNS hostnames Literal IPv4 and IPv6 addresses are not permitted in "HostName"
Here is some code how the server is created:
var certs = {
'intern': {
key: fs.readFileSync(keyName, 'utf8'),
cert: fs.readFileSync(certName, 'utf8')
},
'extern': {
key: fs.readFileSync(keyNameExternal, 'utf8'),
cert: fs.readFileSync(certNameExternal, 'utf8')
}
}
var httpsOpts = {
SNICallback: function (hostname, cb) {
if (hostname === 'mydomain.com') {
var ctx = tls.createSecureContext(certs['extern'])
cb(null, ctx)
}
},
key: fs.readFileSync(keyName, 'utf8'),
cert: fs.readFileSync(certName, 'utf8')
}
httpsServer = https.createServer(httpsOpts, httpsApp)
httpsServer.listen(443, '0.0.0.0', onlisteningHttps)
Is there a possibility to provide certs['intern'] certificate when server is accessed by local IP '192.168.1.100' and provide certs['extern'] certificate when server accessed by public IP (not a hostname)?
It is only possible if your server has two separate interface for internal and external network.
The second parameter to httpsServer.listen
is actually the bind interface. So for example, assume that you have an "internal" interface at 192.168.1.100, you can do this:
httpsServerInt = https.createServer(certs.intern, httpsApp)
httpsServerExt = https.createServer(certs.extern, httpsApp)
httpsServerInt.listen(443, '192.168.1.100', onlisteningHttps)
httpsServerExt.listen(443, '0.0.0.0', onlisteningHttps)
If the server does not have separate interface, you can look into "linux virtual interface" (or windows if that is the case)