Node.js https 服务器:无法监听端口 443 - 为什么?

12 浏览
0 Comments

Node.js https 服务器:无法监听端口 443 - 为什么?

我在Node中首次创建了一个HTTPS服务器,代码(见下文)可以在随机端口(如6643)上工作,但在443端口上无法工作。我得到了以下错误:\n

[调试][服务器]: 初始化...
[调试][控制中心]: 应用程序已初始化...
events.js:72
        throw er; // 未处理的'错误'事件
              ^
错误:listen EACCES
    at errnoException (net.js:904:11)
    at Server._listen2 (net.js:1023:19)
    at listen (net.js:1064:10)
    at Server.listen (net.js:1138:5)
    at Object.module.exports.router (/home/ec2-user/Officeball/Versions/officeball_v0.0.5/server/custom_modules/server.js:52:5)
    at Object. (/home/ec2-user/Officeball/Versions/officeball_v0.0.5/server/control_center.js:15:59)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)

\n这是在Amazon Linux EC2服务器上的情况。据我了解,一旦我将域名的DNS A名称记录设置为服务器的IP,当用户搜索https://mydomain.com时,浏览器将在端口443上查找我的服务器的IP,这是HTTPS流量的标准端口。\n所以我理解我需要通过443端口提供https内容。\n我做错了什么?\n


\n这是我的服务器代码:\ncontrol_center.js(初始化)\n

/* 控制中心 */
//定义全局变量
preloaded = {};
//获取工作路径
var dirPath = process.cwd();
//引入自定义模块
var debug = new (require(dirPath + 
        "/custom_modules/debug"))("控制中心");
var socket = require(dirPath + 
        "/custom_modules/socket")(4546);
// ! 这是相关的代码行
var server = require(dirPath + "/custom_modules/server").router(443);
//应用程序初始化
debug.log("应用程序已初始化...");

\nserver.js\n

/* 服务器 */
//引入NPM模块
var fs      = require('fs'), 
    https   = require('https'), 
    url     = require('url'), 
    path    = require('path');
//获取工作路径
var dirPath = process.cwd();
//引入自定义模块
//省略!
var debug = new (require(dirPath + 
        "/custom_modules/debug"))("服务器");
//预加载请求
var preload = require(dirPath + 
        '/custom_modules/preload').init();
//初始化模块
debug.log("已初始化...");
//定义模块变量
var options = {
  key: fs.readFileSync('SSL/evisiion_private_key.pem'),
  cert: fs.readFileSync('SSL/evisiion_ssl_cert.pem')
};
//监听路径请求
//将请求路由到服务器
module.exports.router = function(port) {
    https.createServer(options, function(req, res) {
        //省略!
    }).listen(port);
};

0
0 Comments

Node.js https服务器无法监听端口443的原因是,在Linux和其他类Unix的操作系统上,服务必须以root用户运行,才能绑定到小于1024的端口号。

解决方法是在开发环境中使用高端口号(如8080),在生产环境中使用像Nginx这样的真正的Web服务器来提供静态内容,并将其他所有内容反向代理到Node应用程序。这样做可以避免以root用户运行应用程序的问题。

你可以使用Nginx来处理静态文件,并将其他内容反向代理到Node应用程序的另一个端口上。下面是一个示例配置文件:

server {
    listen 443;
    server_name example.com;
    client_max_body_size 50M;
    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;
    location /static {
        root /var/www/mysite;
    }
    location / {
        proxy_pass http://127.0.0.1:8000;
    }
}

上述配置假设你的Web应用程序可以通过端口443访问,并且正在运行在端口8000上。如果请求的路径匹配/static文件夹,则从/var/www/mysite/static目录中提供静态文件。否则,Nginx将请求转发到运行在端口8000上的应用程序,可以是Node.js应用程序、Python应用程序或其他应用程序。

使用Nginx作为反向代理解决了该问题,因为应用程序可以通过端口443访问,而不必实际绑定到该端口。

需要注意的是,以root用户身份运行此类服务通常是不明智的做法。这将给予可能存在漏洞的应用程序和所使用的任何NPM模块root访问权限。将其放在Nginx之后可以避免以root用户运行,而且Nginx非常稳定、经过充分测试,并且具有良好的性能和缓存能力。此外,Nginx通常在提供静态内容方面速度更快。

可以使用sudo命令作为解决方案,但这通常被认为是一个不好的做法,因为它会增加应用程序和NPM模块受到攻击的风险。

如果不需要静态文件,可以使用iptables解决端口问题,而无需以root权限运行。如果需要静态文件,最好使用Nginx来处理静态文件,并将其他内容反向代理到Node.js应用程序的端口上。

可以使用process.setgid()process.setuid()方法在监听端口后降低root权限。

使用Nginx作为反向代理可以更轻松地实现压缩响应,并且Nginx已经为你处理了HTTP头,可以更容易地利用浏览器对静态文件的缓存。

在性能方面,Nginx通常被认为比Node.js更快速地提供静态文件。即使Node.js可以做到同样的速度,但需要自己实现相关功能。

Express的创建者明确建议使用反向代理来处理静态文件,而不是使用Express本身来提供静态文件。

还有一些工具,如setcapauthbind,可以允许非root进程设置端口。

无论是否可能,将应用程序放在Nginx之后通常会更高效和更安全。

需要注意的是,虽然在Linux上服务需要以root用户运行才能绑定到小于1024的端口,但这并不意味着一定要以root用户运行服务,这只是一个近似的说法。

0