Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 440 Vote(s) - 3.49 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Is it Possible to Dynamically Return an SSL Certificate in NodeJS?

#1
I want to dynamically return an ssl certificate info in my NodeJS application. I have two domain names linked to the same node application. I only see that the ssl settings can be specified when the server is created. Is it possible to dynamically return ssl certificates based on the requested url?

Otherwise, if I must instead create a second sever instance on another port, will I be able to transparently pipe each request to the original port? Can I make it appear like it's not running on a second port?

Thanks,
Jeff
Reply

#2
`crypto.createCredentials()` is deprecated, so use `tls.createSecureContext()` instead.

[tls.createServer()][1] must have `key` and `cert` in the options, because they are required in the manual. Perhaps `tls.createServer()` uses these parameters as defaults in case `SNICallback` is not supported.

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);
}

Inside the server you can use nodejs package [http-proxy][2] to route your https request to your various applications.


[1]:

[To see links please register here]

[2]:

[To see links please register here]

Reply

#3
Someone who had opened up an issue in [greenlock-express.js](

[To see links please register here]

) and referenced this post, so I'll include the way to do this with *Greenlock for Let's Encrypt* here as well:

Use Greenlock.js for Dynamic SSL Certificates
====

Greenlock does exactly what you need, but bakes in security and convenience.

* Dynamic loading of tls certificates using a structured directory path
* Automated SSL certificate issuance and renewal via Let's Encrypt v2
* Protects against SNI and Host attacks, and domain fronting.

### Install

npm install --save greenlock-express

### Use Let's Encrypt via Greenlock

```js
require("greenlock-express")
.init(function getConfig() {
return { package: require("./package.json") };
})
.serve(httpsWorker);

function httpsWorker(server) {
// Works with any Node app (Express, etc)
var app = require("./my-express-app.js");

// See, all normal stuff here
app.get("/hello", function(req, res) {
res.end("Hello, Encrypted World!");
});

// Serves on 80 and 443
// Get's SSL certificates magically!
server.serveApp(app);
}
```

### Documentation

* HTTP / Express Docs: <https://git.coolaj86.com/coolaj86/greenlock-express.js>.
* API Integration / TCP Docs: <https://git.coolaj86.com/coolaj86/greenlock.js>.
* Screencast Series: [Greenlock for node.js: QuickStart, Config, and Security]()

The video section specifically pertaining to configuration for dynamic domain loading: [2:26 Greenlock for node.js Part 2: Configuration]()

Important Side Note: Security Considerations
====

Greenlock already mitigates these security issues, but if you're implementing by hand there are some things you should know to stay safe:

In particular, it's *really* important to be aware that you can [make yourself vulnerable](

[To see links please register here]

) to SQL injection and/or timing attacks when you are dynamically loading ssl certs with code you write yourself.

Though you expect valid bytes like `example.com` to come through node's `tls.SNICallback(sni, cb)` and `req.socket.servername`, you can actually get a visit from `Robert'); DROP TABLE Students;` (or little [Bobby Tables](

[To see links please register here]

) as we like to call him).

If you're interested in seeing how that exploit could work, I've documented it here in [Greenlock for node.js Part 3: Security Concerns]() and <https://github.com/nodejs/node/issues/22389>

You can also become vulnerable to [Domain Fronting](

[To see links please register here]

), which is a fairly low-risk attack/side-channel, but is important to know and understand.
Reply

#4
Yes, it is possible to do it with one server. But the caveat is that it works on clients that support [SNI][1] - which is most modern browsers.

This is how you do it:

```js

//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'),
// etc
}

//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>);
```

This works because [the options for https][2] is similar to tls.createServer(). Make sure you include all required CA intermediate and root certificates in the crypto.createCredentials call. Also if you have a CA bundle, split them up into multiple single crt files before using them as 'ca' accepts an array of certificates.


[1]:

[To see links please register here]

[2]:

[To see links please register here]

Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through