Habilitación de HTTPS en express.js

Estoy intentando que HTTPS funcione en express.js para el nodo, y no puedo resolverlo.

Este es mi código app.js

 var express = require('express'); var fs = require('fs'); var privateKey = fs.readFileSync('sslcert/server.key'); var certificate = fs.readFileSync('sslcert/server.crt'); var credentials = {key: privateKey, cert: certificate}; var app = express.createServer(credentials); app.get('/', function(req,res) { res.send('hello'); }); app.listen(8000); 

Cuando lo ejecuto, parece que solo responde a las solicitudes HTTP.

Escribí la sencilla aplicación HTTPS de vainilla node.js :

 var fs = require("fs"), http = require("https"); var privateKey = fs.readFileSync('sslcert/server.key').toString(); var certificate = fs.readFileSync('sslcert/server.crt').toString(); var credentials = {key: privateKey, cert: certificate}; var server = http.createServer(credentials,function (req, res) { res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('Hello World\n'); }); server.listen(8000); 

Y cuando ejecuto esta aplicación, responde a las solicitudes HTTPS. Tenga en cuenta que no creo que el resultado toString () en el fs sea importante, ya que he usado combinaciones de ambos y todavía no es bueno.


EDITAR PARA AGREGAR:

Para sistemas de producción, probablemente sea mejor usar Nginx o HAProxy para solicitudes de proxy a la aplicación de su nodo. Puede configurar nginx para manejar las solicitudes ssl y simplemente hablar http a su nodo app.js.

EDITAR PARA AGREGAR (4/6/2015)

Para los sistemas que usan AWS, es mejor que utilice EC2 Elastic Load Balancers para manejar la terminación de SSL y permitir el tráfico HTTP regular a sus servidores web EC2. Para mayor seguridad, configure su grupo de seguridad de modo que solo el ELB pueda enviar tráfico HTTP a las instancias EC2, lo que evitará que el tráfico HTTP desencriptado externo golpee sus máquinas.


En express.js (desde la versión 3) debe usar esa syntax:

 var fs = require('fs'); var http = require('http'); var https = require('https'); var privateKey = fs.readFileSync('sslcert/server.key', 'utf8'); var certificate = fs.readFileSync('sslcert/server.crt', 'utf8'); var credentials = {key: privateKey, cert: certificate}; var express = require('express'); var app = express(); // your express configuration here var httpServer = http.createServer(app); var httpsServer = https.createServer(credentials, app); httpServer.listen(8080); httpsServer.listen(8443); 

De esta forma, proporciona middleware expreso al servidor http / https nativo

Si desea que su aplicación se ejecute en puertos por debajo de 1024, deberá usar el comando sudo (no recomendado) o usar un proxy inverso (por ejemplo, nginx, haproxy).

Me encontré con un problema similar al hacer que SSL funcionara en un puerto diferente al puerto 443. En mi caso, tenía un certificado de paquete, además de un certificado y una clave. El certificado del paquete es un archivo que contiene varios certificados, el nodo requiere que rompa esos certificados en elementos separados de un conjunto.

  var express = require('express'); var https = require('https'); var fs = require('fs'); var options = { ca: [fs.readFileSync(PATH_TO_BUNDLE_CERT_1), fs.readFileSync(PATH_TO_BUNDLE_CERT_2)], cert: fs.readFileSync(PATH_TO_CERT), key: fs.readFileSync(PATH_TO_KEY) }; app = express() app.get('/', function(req,res) { res.send('hello'); }); var server = https.createServer(options, app); server.listen(8001, function(){ console.log("server running at https://IP_ADDRESS:8001/") }); 

En app.js, necesita especificar https y crear el servidor en consecuencia. Además, asegúrese de que el puerto que está tratando de usar permita realmente el tráfico entrante.

Incluyendo puntos:

  1. Configuración de SSL
    1. En config / local.js
    2. En config / env / production.js

Manejo de HTTP y WS

  1. La aplicación debe ejecutarse en HTTP en desarrollo para que podamos depurar fácilmente nuestra aplicación.
  2. La aplicación debe ejecutarse en HTTPS en producción por motivos de seguridad.
  3. La solicitud HTTP de producción de aplicaciones siempre debe redirigirse a https.

Configuración de SSL

En Sailsjs hay dos formas de configurar todo, primero es configurar en la carpeta config con cada uno tiene sus archivos separados (como la conexión de la base de datos con respecto a la configuración se encuentra en connections.js). Y el segundo es configurar la estructura del archivo base del entorno, cada archivo de entorno se presenta en la carpeta config/env y cada archivo contiene configuraciones para env particular.

Velas primero se ve en la carpeta config / env y luego espera config / * .js

Ahora permite la configuración de ssl en config/local.js .

 var local = { port: process.env.PORT || 1337, environment: process.env.NODE_ENV || 'development' }; if (process.env.NODE_ENV == 'production') { local.ssl = { secureProtocol: 'SSLv23_method', secureOptions: require('constants').SSL_OP_NO_SSLv3, ca: require('fs').readFileSync(__dirname + '/path/to/ca.crt','ascii'), key: require('fs').readFileSync(__dirname + '/path/to/jsbot.key','ascii'), cert: require('fs').readFileSync(__dirname + '/path/to/jsbot.crt','ascii') }; local.port = 443; // This port should be different than your default port } module.exports = local; 

Alternativa, puede agregar esto también en config / env / production.js . (Este fragmento también muestra cómo manejar múltiples certificados de CARoot)

O en production.js

 module.exports = { port: 443, ssl: { secureProtocol: 'SSLv23_method', secureOptions: require('constants').SSL_OP_NO_SSLv3, ca: [ require('fs').readFileSync(__dirname + '/path/to/AddTrustExternalCARoot.crt', 'ascii'), require('fs').readFileSync(__dirname + '/path/to/COMODORSAAddTrustCA.crt', 'ascii'), require('fs').readFileSync(__dirname + '/path/to/COMODORSADomainValidationSecureServerCA.crt', 'ascii') ], key: require('fs').readFileSync(__dirname + '/path/to/jsbot.key', 'ascii'), cert: require('fs').readFileSync(__dirname + '/path/to/jsbot.crt', 'ascii') } }; 

http / https & ws / wss redirección

Aquí ws es Web Socket y wss representan Secure Web Socket, cuando configuramos ssl, ahora http y ws ambas solicitudes se vuelven seguras y se transforman a https y wss respectivamente.

Hay muchas fonts de nuestra aplicación que recibirán solicitudes, como cualquier publicación de blog, publicación en redes sociales, pero nuestro servidor solo se ejecuta en https, por lo que cuando cualquier solicitud provenga de http, genera el error “Este sitio no se puede contactar” en el navegador del cliente. Y perdemos el tráfico de nuestro sitio web. Entonces, debemos redirigir la solicitud http a https, las mismas reglas permiten websocket, de lo contrario el socket fallará.

Por lo tanto, debemos ejecutar el mismo servidor en el puerto 80 (http) y desviar todas las solicitudes al puerto 443 (https). Sails primero comstack el archivo config / bootstrap.js antes de levantar el servidor. Aquí podemos iniciar nuestro servidor express en el puerto 80.

En config / bootstrap.js (Crear servidor http y redirigir todas las solicitudes a https)

 module.exports.bootstrap = function(cb) { var express = require("express"), app = express(); app.get('*', function(req, res) { if (req.isSocket) return res.redirect('wss://' + req.headers.host + req.url) return res.redirect('https://' + req.headers.host + req.url) }).listen(80); cb(); }; 

Ahora puede visitar http://www.yourdomain.com , lo redirigirá a https://www.yourdomain.com

Así es como funciona para mí. La redirección utilizada redireccionará todos los http normales también.

 const express = require('express'); const bodyParser = require('body-parser'); const path = require('path'); const http = require('http'); const app = express(); var request = require('request'); //For https const https = require('https'); var fs = require('fs'); var options = { key: fs.readFileSync('certificates/private.key'), cert: fs.readFileSync('certificates/certificate.crt'), ca: fs.readFileSync('certificates/ca_bundle.crt') }; // API file for interacting with MongoDB const api = require('./server/routes/api'); // Parsers app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: false })); // Angular DIST output folder app.use(express.static(path.join(__dirname, 'dist'))); // API location app.use('/api', api); // Send all other requests to the Angular app app.get('*', (req, res) => { res.sendFile(path.join(__dirname, 'dist/index.html')); }); app.use(function(req,resp,next){ if (req.headers['x-forwarded-proto'] == 'http') { return resp.redirect(301, 'https://' + req.headers.host + '/'); } else { return next(); } }); http.createServer(app).listen(80) https.createServer(options, app).listen(443); 

Utilice greenlock-express: SSL gratuito, HTTPS automatizado

Greenlock maneja la emisión y renovación de certificados (a través de Let’s Encrypt) y http => https redirection, out-of-the-box.

express-app.js :

 var express = require('express'); var app = express(); app.use('/', function (req, res) { res.send({ msg: "Hello, Encrypted World!" }) }); // DO NOT DO app.listen() // Instead export your app: module.exports = app; 

server.js :

 require('greenlock-express').create({ // Let's Encrypt v2 is ACME draft 11 version: 'draft-11' , server: 'https://acme-v02.api.letsencrypt.org/directory' // You MUST change these to valid email and domains , email: 'john.doe@example.com' , approveDomains: [ 'example.com', 'www.example.com' ] , agreeTos: true , configDir: "/path/to/project/acme/" , app: require('./express-app.j') , communityMember: true // Get notified of important updates , telemetry: true // Contribute telemetry data to the project }).listen(80, 443); 

Screencast

Mire la demostración de QuickStart: https://youtu.be/e8vaR4CEZ5s

Para Localhost

Simplemente respondiendo esto antes de tiempo porque es una pregunta de seguimiento común:

No puede tener certificados SSL en localhost. Sin embargo, puede usar algo como Telebit que le permitirá ejecutar aplicaciones locales como reales.

También puede usar dominios privados con Greenlock a través de desafíos DNS-01, que se mencionan en el archivo README junto con varios complementos que lo soportan.

Puertos no estándar (es decir, no 80/443)

Lea la nota anterior sobre localhost: tampoco puede usar puertos no estándar con Let’s Encrypt.

Sin embargo, puede exponer sus puertos internos no estándar como puertos estándar externos a través de port-forward, sni-route, o usar algo como Telebit que hace el enrutamiento SNI y el reenvío / retransmisión de puertos por usted.

También puede usar los desafíos de DNS-01, en cuyo caso no tendrá que exponer puertos en absoluto y también puede proteger dominios en redes privadas de esta manera.

Este es mi código de trabajo para Express 4.0 .

Express 4.0 es muy diferente de 3.0 y otros.

4.0 tiene el archivo / bin / www, que va a agregar https aquí.

“npm start” es una forma estándar de iniciar el servidor express 4.0.

La función readFileSync () debería usar __dirname get current directory

while require () use ./ refiérase al directorio actual.

Primero coloque el archivo private.key y public.cert en la carpeta / bin, es la misma carpeta que el archivo WWW .

Primero, vaya a Crear un certificado SSL autofirmado

  • Ir a la terminal y ejecutar el siguiente comando.

sudo openssl req -x509 -nodes -days 365 -newkey rsa: 2048 -keyout ./selfsigned.key -out selfsigned.crt

  • Y poner la siguiente información
  • Nombre del país (código de 2 letras) [AU]: US
  • Nombre del estado o provincia (nombre completo) [Some-State]: NY
  • Nombre de localidad (p. Ej., Ciudad) []: NY
  • Nombre de la organización (p. Ej., Empresa) [Internet Widgits Pty Ltd]: xyz (su – Organización)
  • Nombre de unidad organizacional (por ejemplo, sección) []: xyz (nombre de su unidad)
  • Nombre común (por ejemplo, FQDN del servidor o SU nombre) []: http://www.xyz.com (su URL)
  • Dirección de correo electrónico []: su correo electrónico

Después de la creación, agregue el archivo de clave y cert en su código, Mi bin / archivo www parece.

  var app = require('../app'); var debug = require('debug')('driftApp:server'); //var http = require('http'); var http = require('https'); var fs = require('fs'); var key = fs.readFileSync(__dirname + '/../certs/selfsigned.key'); var cert = fs.readFileSync(__dirname + '/../certs/selfsigned.crt'); var options = { key: key, cert: cert }; var port = normalizePort(process.env.PORT || '3000'); app.set('port', port); console.log("Server Started On Port: ", port); //var server = http.createServer(app); var server = http.createServer(options, app); server.listen(port); server.on('error', onError); server.on('listening', onListening); function normalizePort(val) { var port = parseInt(val, 10); if (isNaN(port)) { // named pipe return val; } if (port >= 0) { // port number return port; } return false; } function onError(error) { if (error.syscall !== 'listen') { throw error; } var bind = typeof port === 'string' ? 'Pipe ' + port : 'Port ' + port; // handle specific listen errors with friendly messages switch (error.code) { case 'EACCES': console.error(bind + ' requires elevated privileges'); process.exit(1); break; case 'EADDRINUSE': console.error(bind + ' is already in use'); process.exit(1); break; default: throw error; } } function onListening() { var addr = server.address(); var bind = typeof addr === 'string' ? 'pipe ' + addr : 'port ' + addr.port; debug('Listening on ' + bind); } 
  • Finalmente ejecute su aplicación usando https