È ansible restituire dynamicmente un certificato SSL in NodeJS?

Voglio restituire dynamicmente un certificato ssl nella mia applicazione NodeJS. Ho due nomi di dominio collegati alla stessa applicazione di nodo. Vedo solo che le impostazioni ssl possono essere specificate quando viene creato il server. È ansible restituire dynamicmente i certificati ssl in base all’URL richiesto?

Altrimenti, se dovessi creare una seconda istanza di sever su un’altra porta, sarò in grado di colbind in modo trasparente ogni richiesta alla porta originale? Posso farlo apparire come se non fosse in esecuzione su una seconda porta?

Grazie, Jeff

Sì, è ansible farlo con un server. Ma l’avvertenza è che funziona su client che supportano SNI – che è la maggior parte dei browser moderni.

Ecco come lo fai:

//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'),  ... ] }).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(); 

Funziona perché le opzioni per https sono simili a tls.createServer (). Assicurati di includere tutti i certificati CA intermedi e root richiesti nella chiamata crypto.createCredentials. Inoltre, se si dispone di un pacchetto di CA, dividerli in più file crt singoli prima di usarli come “ca” accetta un array di certificati.

crypto.createCredentials() è deprecato, quindi usa tls.createSecureContext() .

tls.createServer () deve avere key e cert nelle opzioni, perché sono richieste nel manuale. Forse tls.createServer() utilizza questi parametri come valori predefiniti nel caso in cui SNICallback non sia supportato.

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

All’interno del server è ansible utilizzare il pacchetto http del proxy del pacchetto nodejs per indirizzare la richiesta https alle varie applicazioni.

Qualcuno che ha aperto un problema in greenlock-express.js e ha fatto riferimento a questo post, quindi includerò il modo di farlo con Greenlock per Let’s Encrypt anche qui:

Utilizza Greenlock.js per i certificati SSL dinamici

Greenlock fa esattamente ciò di cui hai bisogno, ma fa il pieno in sicurezza e praticità.

  • Caricamento dinamico dei certificati tls utilizzando un percorso di directory strutturato
  • Rilascio e rinnovo automatico dei certificati SSL tramite Let’s Encrypt v2
  • Protegge dagli attacchi SNI e Host e dal dominio di fronting.

Installare

 npm install --save greenlock-express 

Usa Let’s Encrypt via Greenlock

 'use strict'; require('greenlock-express').create({ version: 'draft-11' , server: 'https://acme-v02.api.letsencrypt.org/directory' , configDir: '~/.config/acme/' // You MUST change these to valid domains // NOTE: all domains will be validated and listed on the certificate , approveDomains: [ 'example.com', 'www.example.com' ] , email: '[email protected]' // For Let's Encrypt emails and Greenlock security updates , agreeTos: true // For Let's Encrypt ToS , communityMember: true // for relevant, but non-critical greenlock updates , telemetry: true // contribute to project telemetry data , app: require('./my-express-app') //, debug: true }); var server = greenlock.listen(80, 443); 

Documentazione

La sezione video specificamente relativa alla configurazione per il caricamento dinamico del dominio: 2:26 Greenlock per node.js Parte 2: Configurazione

Nota importante: considerazioni sulla sicurezza

Greenlock già attenua questi problemi di sicurezza, ma se stai implementando a mano ci sono alcune cose che dovresti sapere per stare al sicuro:

In particolare, è molto importante essere consapevoli che è ansible rendersi vulnerabili agli attacchi SQL injection e / o timing quando si caricano in modo dinamico i certificati ssl con il codice che si scrive.

Anche se ci si aspetta che byte validi come example.com arrivino attraverso il nodo tls.SNICallback(sni, cb) e req.socket.servername , si può effettivamente ottenere una visita da Robert'); DROP TABLE Students; Robert'); DROP TABLE Students; (o piccoli Bobby Tables come ci piace chiamarlo).

Se sei interessato a vedere come questo exploit potrebbe funzionare, l’ho documentato qui in Greenlock per node.js Parte 3: Problemi di sicurezza e https://github.com/nodejs/node/issues/22389

Puoi anche diventare vulnerabile al Domain Fronting , che è un attacco / canale laterale a rischio piuttosto basso, ma è importante conoscerlo e capirlo.