node.js - tls - Habilitando HTTPS en express.js
tls with node (7)
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 la redirección http => https, Greenlock .
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: ''[email protected]''
, 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
Vea la demostración de inicio rápido: https://youtu.be/e8vaR4CEZ5s
Para localhost
Solo respondo 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 aplicaciones reales.
También puede usar dominios privados con Greenlock a través de los desafíos de DNS-01, que se mencionan en el archivo README junto con varios complementos que lo admiten.
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 no estándar internos como puertos estándar externos a través de reenvío de puertos, sni-route, o usar algo como Telebit que realiza enrutamiento SNI y reenvío / reenvío de puertos por usted.
También puede usar los desafíos del DNS-01, en cuyo caso no necesitará exponer los puertos y también puede proteger los dominios en redes privadas de esta manera.
Estoy intentando que HTTPS funcione en express.js para 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í una aplicación HTTPS basada en vanilla node.js
simple:
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 la toString () en el resultado de fs importe, ya que he usado combinaciones de ambos y todavía no es bueno.
EDITAR PARA AÑADIR:
Para los sistemas de producción, probablemente sea mejor usar Nginx o HAProxy para enviar solicitudes a su aplicación nodejs. Puede configurar nginx para manejar las solicitudes ssl y simplemente hablar http a su nodo app.js.
EDITAR A AGREGAR (4/6/2015)
Para los sistemas que usan AWS, es mejor usar los equilibradores de carga elásticos EC2 para manejar la terminación SSL y permitir el tráfico HTTP regular a sus servidores web EC2. Para mayor seguridad, configure su grupo de seguridad de manera que solo el ELB pueda enviar tráfico HTTP a las instancias de EC2, lo que evitará que el tráfico HTTP externo sin cifrar llegue a sus máquinas.
Incluyendo puntos:
- Configuración SSL
- En config / local.js
- En config / env / production.js
Manejo HTTP y WS
- La aplicación debe ejecutarse en HTTP en desarrollo para que podamos depurar fácilmente nuestra aplicación.
- La aplicación debe ejecutarse en HTTPS en producción por motivos de seguridad.
- La solicitud HTTP de producción de aplicaciones siempre debe redirigir a https.
Configuración SSL
En Sailsjs hay dos formas de configurar todas las cosas, primero es configurarlo en la carpeta de configuración, ya que 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 en la estructura de archivos base del entorno, cada uno de los archivos de entorno se presenta en la carpeta config/env
y cada archivo contiene configuraciones para env particular.
Navega primero busca en la carpeta config / env y luego mira adelante a config / * .js
Ahora vamos a configurar 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;
Como alternativa, también puede agregar esto en config / env / production.js . (Este fragmento también muestra cómo manejar múltiples certificados 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'')
}
};
Redirección de http / https & ws / wss
Aquí ws es Web Socket y wss representan Secure Web Socket, ya que configuramos ssl y ahora http y ws ambas solicitudes se vuelven seguras y se transforman en https y wss respectivamente.
Hay muchas fuentes de nuestra aplicación que recibirán solicitudes como cualquier publicación de blog, publicaciones de redes sociales, pero nuestro servidor solo se ejecuta en https, por lo que cuando una solicitud proviene de http, aparece el error "No se puede acceder a este sitio" en el navegador del cliente. Y perdemos el tráfico de nuestro sitio web. Así que debemos redirigir la solicitud http a https, las mismas reglas permiten que websocket, de lo contrario el socket fallará.
Por lo tanto, necesitamos ejecutar el mismo servidor en el puerto 80 (http) y desviar todas las solicitudes al puerto 443 (https). Navega primero compila 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 un 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 , se redirigirá a https://www.yourdomain.com
Así es como funciona para mí. La redirección utilizada también redireccionará a todos los http normales.
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);
En express.js (desde la versión 3) debes usar esa sintaxis:
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 esa manera, 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).
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 agregará https aquí.
"npm start" es la forma estándar en que inicia Express 4.0 server.
La función readFileSync () debería usar __dirname obtener el directorio actual
mientras requiera () use ./ refiérase al directorio actual.
Primero coloque los archivos private.key y public.cert en la carpeta / bin, es la misma carpeta que el archivo WWW .
Me encontré con un problema similar al hacer que SSL funcionara en un puerto distinto al puerto 443. En mi caso, tenía un certificado de paquete, un certificado y una clave. El certificado de paquete es un archivo que contiene varios certificados; el nodo requiere que se rompan esos certificados en elementos separados de una matriz.
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 debe especificar https y crear el servidor en consecuencia. Además, asegúrese de que el puerto que está intentando usar realmente permita el tráfico entrante.
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]: EE . UU.
- Nombre del estado o provincia (nombre completo) [algún estado]: NY
- Nombre de localidad (por ejemplo, ciudad) []: NY
- Nombre de la organización (p. Ej., Compañía) [Internet Widgits Pty Ltd]: xyz (su - Organización)
- Nombre de la unidad organizativa (p. Ej., Sección) []: xyz (nombre de su unidad)
- Nombre común (p. Ej., FQDN del servidor o SU nombre) []: www.xyz.com (su URL)
- Dirección de correo electrónico []: su correo electrónico
Después de la creación, agregue la clave y el archivo cert en su código, el archivo Mi bin / 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