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

13

我第一次在Node中创建HTTPS服务器,以下是代码。在像6643这样的随机端口上可以运行,但在443端口上就不能工作。我遇到了以下错误:

[Debug][Server]: Initialized...
[Debug][Control Center]: Application initialized...

events.js:72
        throw er; // Unhandled 'error' event
              ^
Error: 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.<anonymous> (/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)

我在一个亚马逊Linux EC2服务器上。据我所知,一旦我将我的域名的DNS A名称记录设置为服务器的IP,当用户搜索https://mydomain.com时,浏览器将在标准HTTPS流量端口443上查找我的服务器IP。

因此,我的理解是我需要通过443端口提供https内容。

我做错了什么?


这是我的服务器代码:

control_center.js(init)

/* Control Center */

//DEFINE GLOBALS

preloaded = {};

//GET DIRECT WORKING PATH

var dirPath = process.cwd();

//REQUIRE CUSTOM MODULES 

var debug = new (require(dirPath + 
        "/custom_modules/debug"))("Control Center");
var socket = require(dirPath + 
        "/custom_modules/socket")(4546);

// ! this is the relevant line
var server = require(dirPath + "/custom_modules/server").router(443);

//APP INITIALIZE

debug.log("Application initialized...");

服务器.js

/* Server */

//REQUIRE NPM MODULES

var fs      = require('fs'), 
    https   = require('https'), 
    url     = require('url'), 
    path    = require('path');

//GET DIRECT WORKING PATH

var dirPath = process.cwd();

//REQUIRE CUSTOM MODULES

//Snip!

var debug = new (require(dirPath + 
        "/custom_modules/debug"))("Server");

//Preload requests

var preload = require(dirPath + 
        '/custom_modules/preload').init();

//INIT MODULE 

debug.log("Initialized...");

//DEFINE MODULE VARIABLES

var options = {
  key: fs.readFileSync('SSL/evisiion_private_key.pem'),
  cert: fs.readFileSync('SSL/evisiion_ssl_cert.pem')
};

//LISTEN FOR PATH REQUESTS

//route requests to server
module.exports.router = function(port) {
    https.createServer(options, function(req, res) {

        //Snip!

    }).listen(port);
};

可能不是代码的问题,请查看这里 - Brendan
@BrendanAshworth 当它变得如此简单,以至于它伤人... - user3818284
唯一的原因是因为我之前回答过相同的问题 :) 如果那个答案没有解决问题,可能还涉及到根用户权限。 - Brendan
1
点击此处以获取一个iptables解决方案,该解决方案允许端口在非root用户下使用。另请参阅此处,其中包括了一个几乎相同的问题和答案。 - jfriend00
1个回答

33

在 Linux 上(以及我相信大多数其他类 Unix 操作系统上),一个服务必须以 root 用户的身份运行才能绑定到小于1024的端口号。

我刚刚在一款我拥有的 Node 应用程序上验证了这一点,当我将端口从5000更改为443时,除文件路径外,每一行代码的错误都完全相同。

在开发过程中,大多数人会在高编号端口(例如8080)上运行开发服务器。在生产环境中,您可能希望使用像 Nginx 这样的真正的 Web 服务器来提供静态内容,并将其他所有内容反向代理到您的 Node 应用程序,这使得它不再是一个问题,因为 Nginx 可以愉快地以 root 用户身份运行。

编辑:由于您的用例需要提供一些静态内容,则可能希望使用像 Nginx 或 Apache 这样的 Web 服务器处理静态文件,并将动态内容反向代理到另一个端口。使用 Nginx 进行反向代理非常简单 - 这里是一个示例配置文件:

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应用程序或任何其他应用程序。

这也相当妙,因为应用程序将在端口443上可访问,而无需实际绑定到该端口。

应该说,作为一个通常的经验法则,像这样以root身份运行服务并不是一个好主意。您将授予应用程序可能存在漏洞和您引入的任何NPM模块的root访问权限。例如,将其置于Nginx后面将意味着您无需以root身份运行它,而且Nginx很坚实、经过充分测试,具有良好的性能和缓存能力。此外,Nginx通常会更快地提供特定的静态内容服务。


你是对的,只需要加上魔法词就可以立即运行了。一定要爱 sudo - user3818284
3
在网络服务器中使用root访问权限通常是一个不好的做法,因为这会增加您可能面临的安全漏洞数量。请参考我在您的问题评论中提供的两个帖子,了解在不使用root运行节点进程的情况下,在低端口上侦听的替代方法。我个人正在使用iptables解决方案。 - jfriend00
@jfriend00 刚好比我快!如果您不需要提供任何静态文件,那么iptables解决方案是一个很好的选择。如果您需要提供静态文件,我认为最好按照我所提到的方法 - 使用Nginx提供静态文件,并将其他所有内容反向代理到Node.js应用程序正在运行的端口。 - Matthew Daly
1
@jt0dd 嗯,像Apache和Nginx这样的Web服务器是可靠、广泛使用的产品,它们很可能比我们大多数人自己创建的任何定制解决方案表现更好,也更安全。 Nginx通常被认为比Apache更快地服务于静态内容,使其成为此用例的理想选择。 它还通过允许您在所需端口上运行Nginx来完美地解决了此问题。 配置Nginx相当容易 - 我会在我的答案中添加一个示例配置。 - Matthew Daly
1
在我看来,只有在你真的需要额外一个 web 服务器层来提供静态文件时,你才应该增加设置的复杂性。我的网站根本不需要它(node 自己就可以正常工作),所以在这种情况下,简单是更好的选择。除非确实需要更 多的复杂性,否则 OP 应该保持简单。iptables 解决了端口问题,而且不需要使用 root 权限。 - jfriend00
显示剩余12条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接