0

I set up a express project using express-generator, now I'm trying to convert it into working with a cloudflare SSL Certificate over https.

I run my express app on port 443.

However when I then go to the domain I get the cloudflare 522 error, I cannot figure what's causing this even after reading the docs.

Server Code

#!/usr/bin/env node

/**
 * Module dependencies.
 */

var app = require('../app');
var debug = require('debug')('myapp:server');
var http = require('http');

/**
 * Get port from environment and store in Express.
 */

var port = normalizePort(process.env.PORT || '443');

app.set('port', port);

/**
 * Create HTTP server.
 */

var fs = require('fs')
var https = require('https');
var options = {
  key: fs.readFileSync(__dirname + '/certs/key.pem'),
  cert: fs.readFileSync(__dirname + '/certs/cert.pem')
};

var server = https.createServer(options, app);

/**
 * Listen on provided port, on all network interfaces.
 */

server.listen(port);
server.on('error', onError);
server.on('listening', onListening);

/**
 * Normalize a port into a number, string, or false.
 */

function normalizePort(val) {
  var port = parseInt(val, 10);

  if (isNaN(port)) {
    // named pipe
    return val;
  }

  if (port >= 0) {
    // port number
    return port;
  }

  return false;
}

/**
 * Event listener for HTTP server "error" event.
 */

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;
  }
}

/**
 * Event listener for HTTP server "listening" event.
 */

function onListening() {
  var addr = server.address();
  var bind = typeof addr === 'string'
    ? 'pipe ' + addr
    : 'port ' + addr.port;
  debug('Listening on ' + bind);
}

ofwhich the server is created in this part;

var fs = require('fs')
var https = require('https');
var options = {
  key: fs.readFileSync(__dirname + '/certs/key.pem'),
  cert: fs.readFileSync(__dirname + '/certs/cert.pem')
};

var server = https.createServer(options, app);
Borda
  • 139
  • 1
  • 10

1 Answers1

0

I run my express app on port 3000 and use iptables to forward traffic from 80 and 443 to my app (3000).

Based on your code your nodejs app will handle https. It will not handle plain HTTP. But by simple forwarding port 80 to port 3000 plain HTTP requests will be send to the application.

... when I then go to the domain I get the cloudflare 522 error

The default protocol if you just "go to the domain" is HTTP. This means your browser will send a HTTP request on port 80 to Cloudflare which then will forward this plain HTTP request to your system on port 80 where you will then forward this plain HTTP request to your nodejs application on port 3000. Only, this application cannot handle the plain HTTP. Instead it expects HTTPS which means it expects the start of the TLS handshake (ClientHello) and not a plain HTTP request. This might result in the error you see since the nodejs application might wait for the expected input and not respond to the plain HTTP request.

To fix the problem you might for example let the nodejs application listen for both HTTP and HTTPS on different ports as described here and then redirect 80 to the http-listener and 443 to the https-listener.

Steffen Ullrich
  • 114,247
  • 10
  • 131
  • 172
  • Well, I flushed the iptables and now I am just running the entire app on `443`, that should then work, would it not? It still does not, but I will also be trying what you suggest. Edit: also I am using https in the domain. – Borda Jan 03 '19 at 22:25
  • I want a user the be forced to use https, so it would not be a problem to not even run a http server. Edit: I have also tried `https://domain:443` which still results in the same error – Borda Jan 03 '19 at 22:29
  • @Borda: did you make sure that the app is actually reachable from outside? I.e. did you check that `openssl s_client -connect real-ip:443 -servername your-host` successfully connects from outside the host, where `real-ip` is the IP address of your server (the one you gave to cloudflare) and `your-host` is your hostname? – Steffen Ullrich Jan 04 '19 at 05:16