Express 3.0 HTTPS - node.js

I have a Node.js Express 3.0 application which listens on port 3000 locally and 80 online, that's fine. What I need to do now however is introduce an SSL certificate.
I've looked at many sources online however they're all dated, or only work on port 443 or nothing. What I need to do however is listen on both 443 and 80 and re-direct any requests to 80 back to 443.
Are they any up to date examples of this?

I would do this with 2 distinct processes: an insecure proxy server and a secure server.
The insecure proxy listens on port 80 and responds to all requests with a 302 redirect to the secure server
Insecure Proxy
var http = require('http')
var port = 80
var server = http.createServer(function (req, res) {
// change this to your secure sever url
var redirectURL = 'https://www.google.com'
res.writeHead(302, {
Location: redirectURL
});
res.end();
}).listen(port, function () {
console.log('insecure proxy listening on port: ' + port)
})
Secure Server
var https = require('https')
var express = require('express')
var fs = require('fs')
var keyFilePath = '/path/to/key.pem'
var certFilePath = '/path/to/cert.pem'
var app = express()
// put your express app config here
// app.use(...) etc.
var port = 443 // standard https port
var options = {
key: fs.readFileSync(keyFilePath, 'utf8'),
cert: fs.readFileSync(certFilePath, 'utf8')
}
var server = https.createServer(options, app)
server.listen(port, function () {
console.log('secure server listening on port: ' + port)
})
Note that you could run both of these servers within a single process but it is more maintainable to separate the concerns into distinct processes.

Related

Express.js. How to generate a valid ssl certificate?

I have a production ready express server. And 2 webapps working with it.
The express server is in the port : 1111
I have created two letsencrypt ssl for my nginx server, and im using it with the frontend sites for app.domain.com and domain.com, it works fine.
The point is that the backend isnt reached because it must be ssl too. But... how do I setup a valid ssl for my backend? I mean I cant do it with letsencrypt because its a backend server and it doesn't have ssl.
I have tried using the same certificates that i generated for domain.com in the express server using basically this code taken from other site
// Dependencies
const fs = require('fs');
const http = require('http');
const https = require('https');
const express = require('express');
const app = express();
// Certificate
const privateKey = fs.readFileSync('/etc/letsencrypt/live/yourdomain.com/privkey.pem', 'utf8');
const certificate = fs.readFileSync('/etc/letsencrypt/live/yourdomain.com/cert.pem', 'utf8');
const ca = fs.readFileSync('/etc/letsencrypt/live/yourdomain.com/chain.pem', 'utf8');
const credentials = {
key: privateKey,
cert: certificate,
ca: ca
};
app.use((req, res) => {
res.send('Hello there !');
});
// Starting both http & https servers
const httpServer = http.createServer(app);
const httpsServer = https.createServer(credentials, app);
httpServer.listen(80, () => {
console.log('HTTP Server running on port 80');
});
httpsServer.listen(443, () => {
console.log('HTTPS Server running on port 443');
});
But it worked randomly, a lot of times the request timed out because it took forever, and other times it worked, it was weird.
But now it suddenly even stopped working, so I dont know what to do there.
What type of certificate do I have to use?
Self signed ones are rejected by chrome, and I donty know how else to generate a letsencrypt one, if the express node server is running in an ip not a domain
Okey, the problem was with my nginx virtualhosts. I created a virtualhost api.domain.com
server
{
listen 443;
listen [::]:443;
server_name api.domain.com;
location /
{
proxy_pass https://127.0.0.1:1111;
}
}
And then run
sudo certbot --nginx -d api.domain.com
Then it started to work

Https server with socket and express

I'm using SSL to encrypt my backend but my current solution opens two ports, one for sockets and the other for express, any approach to start both on the same port like HTTP ?
const port=4000;
if(process.env.ENABLE_SSL=='true')
{
////two ports are open 8989,4000
server = https.createServer({
key: fs.readFileSync("sslLocation/ssl.key"),
cert: fs.readFileSync("sslLocation/ssl.cert")
},app).listen("8989", '0.0.0.0',function(){
console.log('Express server listening to port 8989');
});
global.io = require('socket.io').listen(server);
app.listen(port);
}
else
{
////one port only
// start the server
server = app.listen(port, function () {
console.log(`App is running at: localhost:${server.address().port}`);
});
global.io = require('socket.io').listen(server);
}
also running app.listen(server) in the ssl section, i can't access the apis

Express HTTPS - unable to connect securely- SSLv3 broken protocol

Trying to make HTTPS server work on Express 4, however, there's an SSLv3 security error coming (please see the image). To my understanding SSLv3 protocol is not supported by browsers anymore due to POODLE attack.
How to make HTTPS server use the TLS1.2 protocol?
var express = require('express'),
app = express(),
fs = require('fs'),
https = require('https'),
key = fs.readFileSync('/usr/local/etc/ssl/key.pem'),
cert = fs.readFileSync('/usr/local/etc/ssl/cert.pem'),
https_options = {
key: key,
cert: cert
},
PORT = 8000,
HOST = 'localhost';
https.createServer(https_options.key, app).listen(PORT);
app.get('/', function(req, res) {
res.send('Hello');
});
module.exports = app;
The server is listening localhost:8000
The error
try to create server like that
it is working fine at my side,
var server = require('https').createServer(options, app),
server.listen(port);
or if like to add socket
var server = require('https').createServer(options, app),
io = require('socket.io').listen(server);
server.listen(port);

Cannot enable my own SSL certificate on heroku

I host my website at heroku using my own domain name using node.js & express 4.x.
I have purchased SSL certificate and I want to add it to my website.
I use the following code to enable HTTPS support:
var fs = require('fs');
var http = require('http');
var https = require('https');
var privateKey = fs.readFileSync('sec/private_server.key', 'utf8');
var certificate = fs.readFileSync('sec/server.crt', 'utf8');
var credentials = { key: privateKey, cert: certificate };
// launch http server
var httpServer = http.createServer(app).listen( process.env.PORT, process.env.IP || "0.0.0.0", function() {
console.log('Listening on port %d', process.env.PORT);
});
// launch https server
var httpsServer = https.createServer(credentials, app).listen( 8443, process.env.IP || "0.0.0.0", function() {
console.log('Listening HTTPS on port 8433' );
});
Launching the server and visiting it by https link shows that I this website still uses heroku certificate.
What do I do wrong?
You need to use the Heroku SSL endpoint add-on.
https://devcenter.heroku.com/articles/ssl-endpoint

Node.js + Express.js + Socket.io on port 443 (HTTPS TLS/SSL)

I have an app with Node.js, Express.js, and Socket.io that runs fine using ANY port except 443. The server is meant to only operate over HTTPS port 443 and likewise, the websocket should be encrypted as well.
CODE THAT WORKS
var fs = require('fs');
var https = require('https');
var express = require('express');
var socket = require('socket.io');
var sslOptions = {
key: fs.readFileSync(__dirname + '/../ssl/server.key,
cert: fs.readFileSync(__dirname + '/../ssl/server.pem,
ciphers: 'ECDHE-RSA-AES256-SHA:AES256-SHA:RC4-SHA:RC4:HIGH:!MD5:!aNULL:!EDH:!AESGCM',
honorCipherOrder: true
};
var app = express();
var server = https.createServer(sslOptions, app);
var io = socket.listen(server, {
"log level" : 3,
"match origin protocol" : true,
"transports" : ['websocket']
});
server.listen(8443);
When I change the port (last line) to 443, the Node server crashes right away with an error:
warn: error raised: Error: listen EADDRINUSE
Apparently you've already got a server listening on that port on your machine. Is is possible that you started this server elsewhere and it's still running?
It means that the port is in use, you can check using :
sudo netstat -tapen | grep ":443".
If you use Apache, Ngnix or other server it is likely to be it.

Resources