1

While I am setting up a NodeJS app on Ubuntu 16.04, I have faced some strange behaviour. App is only works with http dependency but not with https dependency.

My NodeJS app is running on port 8081 and I'm using Nginx reverse proxy with SSL to redirect calls to the 8081 port. Following is my default.conf file in Nginx site-enabled directory.

# HTTP - redirect all requests to HTTPS:
server {
        listen 80;
        listen [::]:80 default_server ipv6only=on;
        return 301 https://$host$request_uri;
}

# HTTPS - proxy requests on to local Node.js app:
server {
        listen 443;
        server_name test.com;

        ssl on;
        # Use certificate and key provided by Let's Encrypt:
        ssl_certificate /etc/letsencrypt/live/test.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/test.com/privkey.pem;
        ssl_session_timeout 5m;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_prefer_server_ciphers on;
        ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';

        # Pass requests for / to localhost:8081:
        location / {
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-NginX-Proxy true;
                proxy_pass http://localhost:8081/;
                proxy_ssl_session_reuse off;
                proxy_set_header Host $http_host;
                proxy_cache_bypass $http_upgrade;
                proxy_redirect off;
        }
}

Following is the test script I'm running on Node server.

var https = require('https');
https.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Welcome to Test App');
}).listen(8081, 'localhost');
console.log('Server running at http://localhost:8081/');

I'm getting 502 Bad Gateway when I test site using test.com. But strangely when I change the https dependency to http everything works like a charm.

What might be the issue for the strange behaviour? Can't we use https with SSL setup with Nginx? Since I'm looking to use trusted peer connection it's necessary to use https with NodeJS as well.

6
  • Does the nginx error log (in /var/log/nginx) reveal anything? Also, if you don't use any forwarding, can you access the nginx default homepage without any issue? Commented Apr 29, 2017 at 3:20
  • Also, from what I see you are broadcasting on https://localhost:8081/ (despite not configuring security keys on the node server for your test) but forwarding to non-https URL at http://localhost:8081/ Commented Apr 29, 2017 at 3:28
  • @nb1987 There is one. 23828#23828: *32 upstream prematurely closed connection while reading response header from upstream, client: 123.123.106.254, server: test.com, request: "GET / HTTP/1.1", upstream: "127.0.0.1:8081", host: "test.com" Commented Apr 29, 2017 at 3:51
  • Okay...I just have a couple more questions. 1.) Is the value of proxy_pass still http://localhost:8081/; ? Do you still get the same error if you set it to https://localhost:8081/; ? 2.) Can you see what error Node itself throws? You can assign the result of http.createServer to a variable and listen for error: e.g., var server = http.createServer(function ... then server.on('error', function (e) { console.log(e); }); Commented Apr 29, 2017 at 3:59
  • I just set it to https://localhost:8081/ and it's working. I have tried this before but didn't work. It's working now. Please add as an answer to accept it. Commented Apr 29, 2017 at 4:10

1 Answer 1

3

Since your Node.js application is listening on https, your Nginx server should forward requests to https://localhost:8081/ rather than http://localhost:8081, so you should set your proxy_pass value to https://localhost:8081/

Sign up to request clarification or add additional context in comments.

4 Comments

This works fine until I add SSL options in the NodeJS. var options = { key: fs.readFileSync(config.keypath), ca: [fs.readFileSync(config.capath)], cert: fs.readFileSync(config.certpath), requestCert: true, rejectUnauthorized: true }; With this code specially when I add requestCert: true this error start happening again.
Do connections work OK (either directly or through Nginx) without requestCert? Also, the default setting for requestCert is false and in typical configurations it will indeed be false. But, if you are certain that you need it set to true, I would recommend trying to find out what errors Node itself reports. Could you try listening for the error event by adding one such event listener to your server using the sample code I provided in the comments to your initial question? In that case, what error does Node report?
I used it. There are no errors. NodeJS script is working fine at test.com:8081 but not on naked domain when I use requestCert: true. I need to use this as I want only the users with the certificate to access it.
To be honest in my own applications I have never exposed the Node server to the outside so I have only needed to configure TLS/SSL on the Nginx server. However, I suspect that in this scenario you would need to authenticate Nginx to the upstream server by setting the proxy_ssl_certificate and proxy_ssl_certificate_key directives under your location / block. This guide may be of help: nginx.com/resources/admin-guide/nginx-https-upstreams

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.