(OP did request to see my nodejs proxy code in comment from another answer.)
Before we jump into nodejs proxy, we should check several things:
Certificate
Is your certificate valid for both with and without www?
If your certificate is only valid for without www (or the other way round), then no proxy (nginx or mine or any other) setting can help. Because the SSL/TLS handshake happen BEFORE redirect. The browser will complaint right away, before any redirect happen. End user see certificate error in browser.
Mine is valid for both and you can check out my blog https://johnsiu.com and https://www.johnsiu.com . The redirect happen without any certificate complain.
DNS
Is your DNS setup correctly for both with and without www? They should point to the same IP address.
I am wondering if this has anything to do with the ERR_SOCKET_NOT_CONNECTED error.
Nodejs Proxy
It is hosted in ghithub: https://github.com/J-Siu/ghost-https-nodejs-proxy
I just finish fine tuning my nodejs proxy, following is the latest version:
// HTTPS
const fs = require('fs');
const url = require('url');
const http = require('http');
const https = require('spdy'); // http2 support
const proxy = require('http-proxy').createProxyServer();
const compression = require('compression');
const ex = require('express')();
const fqdn = '<your domain name here>';
// Fill in your certificate files
const serverKey = '<KEY file>';
const serverCrt = '<CRT file>';
//const serverCa='<CA file>';
const httpsOptions = {
key: fs.readFileSync(serverKey),
cert: fs.readFileSync(serverCrt),
// ca: fs.readFileSync(serverCa),
ciphers: [
"ECDHE-RSA-AES256-SHA384",
"DHE-RSA-AES256-SHA384",
"ECDHE-RSA-AES256-SHA256",
"DHE-RSA-AES256-SHA256",
"ECDHE-RSA-AES128-SHA256",
"DHE-RSA-AES128-SHA256",
"HIGH",
"!aNULL",
"!eNULL",
"!EXPORT",
"!DES",
"!RC4",
"!MD5",
"!PSK",
"!SRP",
"!CAMELLIA"
].join(':'),
};
// Ghost Proxy configuration
proxy.on('proxyReq', function (proxyReq, req, res, options) {
// Ngix: proxy_set_header Host $http_host;
proxyReq.setHeader('Host', req.headers.host);
// Ngix: proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxyReq.setHeader('X-Forwarded-For', req.connection.remoteAddress);
// Ngix: proxy_set_header X-Forwarded-Proto $scheme;
proxyReq.setHeader('X-Forwarded-Proto', 'https');
});
ex
.use(compression())
.use((req, res) => {
if (req.header.host == fqdn) {
proxy.web(req, res, { target: 'http://localhost:2368' });
} else {
res.writeHead(301, { 'location': 'https://' + fqdn + req.url });
res.end();
}
})
// HTTPS Server
https.createServer(httpsOptions, ex).listen(443, '0.0.0.0');
// HTTP Redirect to HTTPS
http.createServer(function (req, res) {
res.writeHead(301, { 'location': 'https://' + fqdn + req.url });
res.end();
}).listen(80, '0.0.0.0');
It is able to:
- redirect any http traffic to https (I am not checking url here)
- redirect any https traffic to the correct fqdn (any request not matching my fqdn is redirected)
ab
test show ~16request/sec
I create this for my single box single site setup and specifically to avoid any apache/nginx package while supporting HTTPS/HTTP2. This may not suite your need completely as you are doing multiple sites.