Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Configuring HTTPS for Express and Nginx

Tags:

I am trying to configure my ExpressJS app for https connection. The Express server runs at localhost:8080 and the secure one localhost:8443.

Here is the server.js code related to https:

var app = express();  var https = require('https');  const options = {     cert: fs.readFileSync('/etc/letsencrypt/live/fire.mydomain.me/fullchain.pem'),     key: fs.readFileSync('/etc/letsencrypt/live/fire.mydomain.me/privkey.pem') };  app.listen(8080, console.log("Server running")); https.createServer(options, app).listen(8443, console.log("Secure server running on port 8443")); 

And here is my Nginx configuration:

server {     listen 80;     listen [::]:80;     server_name fire.mydomain.me;      location / {         proxy_pass http://localhost:8080;         proxy_http_version 1.1;         proxy_set_header Upgrade $http_upgrade;         proxy_set_header Connection 'upgrade';         proxy_set_header Host $host;         proxy_cache_bypass $http_upgrade;     } }  server {     listen 443;     listen [::]:443;     server_name fire.mydomain.me;     location / {         proxy_pass https://localhost:8443;         proxy_http_version 1.1;         proxy_set_header Upgrade $http_upgrade;         proxy_set_header Connection 'upgrade';         proxy_set_header Host $host;         proxy_cache_bypass $http_upgrade;     } } 

What I did :

  • Generating SSL certificate with Letsencrypt certonly tool for the domain fire.mydomain.me.
  • Configuring nginx.
  • Configuring the server.js node app.
  • Adding TCP rules for the 443 port in Ufw.

I tried

  • Commenting the not-ssl server line in server.js to force the connections to go through ssl configuration: this serve the page when I try to go to fire.mydomain.me:443 but not to "https:// fire.mydomain.me". In both cases, no SSL. Trying to go to https:// fire.mydomain.me generate this message "This website doensn't provide a secure connection" in Google Chrome.

  • I followed this tutorial in the first place to set my ssl node config : https://medium.com/@yash.kulshrestha/using-lets-encrypt-with-express-e069c7abe625#.93jgjlgsc

like image 331
Guillaume Avatar asked Mar 13 '17 11:03

Guillaume


People also ask

How do I enable HTTPS on nginx?

Setting up an HTTPS Server. To set up an HTTPS server, in your nginx. conf file include the ssl parameter to the listen directive in the server block, then specify the locations of the server certificate and private key files: server { listen 443 ssl; server_name www.example.com; ssl_certificate www.

Can HTTPS use Express?

You should now understand how to set up a NodeJS HTTPS web service using the Express framework. By simply installing the Express NodeJS package and creating a simple configuration script, you can have a secure web service running over HTTPS.

Can I use Express with nginx?

Express runs only in node. js. Usually, when you combine nginx with Express, you direct the incoming requests to nginx. It then applies whatever you want nginx to do and then forwards remaining requests to your express port (which, if on the same host, is a different port from what the user connected to).

How do I force HTTP to HTTPS nginx?

Redirect HTTP to HTTPS version for Specified domain in Nginx Server_name domain-name.com www.domain-name.com – it specifies the domain names. So, replace it with your website domain name that you want to redirect. Return 301 https://domain-name.com$request_uri – it moves the traffic to the HTTPS version of the site.


2 Answers

You don't need to use HTTPS between your nginx reverse proxy and Node app running on the same host. You can proxy both HTTP requests to port 80 and HTTPS requests to port 443 to the same port in your Node app - 8080 in this case - and you don't need to configure TLS certificates in that case.

You can change your server.js file to:

var app = express();  app.listen(8080, console.log("Server running")); 

and use an nginx config that has proxy_pass http://localhost:8080; for both HTTP on port 80 and HTTPS on port 443.

This is how it is usually done. Encrypting traffic on the loopback interface doesn't add any security because to sniff the traffic you need root access to the box and when you have it then you can read the certs and decrypt the traffic anyway. Considering the fact that most of the posts on https://nodejs.org/en/blog/vulnerability/ are related to OpenSSL, one could argue that using SSL in Node can make it less secure in that particular case of encrypting loopback interface traffic. See this discussion on the Node project on GitHub for more info.

like image 69
rsp Avatar answered Sep 17 '22 19:09

rsp


Thanks to @rsp solution, here is the working Nginx configuration :

server { listen 80; listen 443 ssl;  server_name fire.mydomain.me;  ssl_certificate     /etc/letsencrypt/live/fire.mydomain.me/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/fire.mydomain.me/privkey.pem;  location / {     proxy_pass http://localhost:8080;     proxy_http_version 1.1;     proxy_set_header Upgrade $http_upgrade;     proxy_set_header Connection 'upgrade';     proxy_set_header Host $host;     proxy_cache_bypass $http_upgrade;    } } 
like image 42
Guillaume Avatar answered Sep 19 '22 19:09

Guillaume