【问题标题】:Cloudflare SSL Err 522 ExpressCloudflare SSL Err 522 Express
【发布时间】:2026-01-21 02:10:01
【问题描述】:

我使用express-generator 设置了一个express 项目,现在我正在尝试将其转换为使用cloudflare SSL Certificate 而不是https

我在端口 443 上运行我的 express 应用程序。

但是,当我转到域时,我得到了 cloudflare 522 错误,即使在阅读了文档之后,我也无法弄清楚是什么原因造成的。

服务器代码

#!/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);
}

这部分创建的服务器;

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

【问题讨论】:

    标签: javascript node.js express ssl express-generator


    【解决方案1】:

    我在端口 3000 上运行我的 express 应用,并使用 iptables 将流量从 80 和 443 转发到我的应用 (3000)。

    根据您的代码,您的 nodejs 应用程序将处理 https。它不会处理纯 HTTP。但是通过简单地将端口 80 转发到端口 3000,普通的 HTTP 请求将被发送到应用程序。

    ...当我转到域时,我得到 cloudflare 522 错误

    如果您只是“转到域”,默认协议是 HTTP。这意味着您的浏览器将在端口 80 上向 Cloudflare 发送一个 HTTP 请求,然后 Cloudflare 会将这个纯 HTTP 请求转发到您的系统的端口 80,然后您将这个纯 HTTP 请求转发到端口 3000 上的 nodejs 应用程序。只是,这个应用程序不能处理纯 HTTP。相反,它需要 HTTPS,这意味着它需要 TLS 握手 (ClientHello) 的开始,而不是普通的 HTTP 请求。这可能会导致您看到错误,因为 nodejs 应用程序可能会等待预期的输入而不响应纯 HTTP 请求。

    要解决此问题,您可以让 nodejs 应用程序在不同的端口 as described here 上同时侦听 HTTP 和 HTTPS,然后将 80 重定向到 http-listener 并将 443 重定向到 https-listener。

    【讨论】:

    • 好吧,我刷新了 iptables,现在我只是在 443 上运行整个应用程序,这应该可以工作,不是吗?它仍然没有,但我也会尝试你的建议。编辑:我也在域中使用 https。
    • 我希望用户被强制使用 https,所以即使不运行 http 服务器也不会有问题。编辑:我也试过https://domain:443 仍然导致同样的错误
    • @Borda:您是否确保该应用程序实际上可以从外部访问? IE。您是否检查过openssl s_client -connect real-ip:443 -servername your-host 是否从主机外部成功连接,其中real-ip 是您的服务器的IP 地址(您提供给cloudflare 的那个),your-host 是您的主机名?