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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26579028/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-22 23:05:25  来源:igfitidea点击:

Node.js https server: Can't listen to port 443 - Why?

javascriptnode.jssslhttpsamazon-ec2

提问by Matthew Daly

I'm creating a an HTTPS server for the first time in Node, and the code (see below) works for a random port like 6643 but on port 443, it won't work. I get this error:

我第一次在 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)

This is on an Amazon Linux EC2 server. It's my understanding that once I set my domain's DNS A Name Record to the server's IP, when a user searches https://mydomain.com, the browser will look up my server's IP at port 443, which is supposedly the standard port for HTTPS traffic.

这是在 Amazon Linux EC2 服务器上。我的理解是,一旦我将域的 DNS A 名称记录设置为服务器的 IP,当用户搜索https://mydomain.com 时,浏览器将在端口 443 处查找我的服务器的 IP,这应该是 HTTPS 的标准端口交通。

So my understanding is that I need to serve https content via port 443.

所以我的理解是我需要通过端口 443 提供 https 内容。

What am I doing wrong?

我究竟做错了什么?



Here's my server code:

这是我的服务器代码:

control_center.js (init)

control_center.js(初始化)

/* 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...");

server.js

服务器.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);
};

回答by Matthew Daly

On Linux (and, I believe, most other Unix-like operating systems), a service has to run as root to be able to bind to a port numbered less than 1024.

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

I've just verified it on a Node app I had lying around, and I saw exactly the same error, line for line identical barring the file paths, when I changed the port from 5000 to 443.

我刚刚在我身边的 Node 应用程序上验证了它,当我将端口从 5000 更改为 443 时,我看到了完全相同的错误,一行行相同,除非文件路径相同。

In development, most people will run the dev server on a higher-numbered port such as 8080. In production, you might well want to use a proper web server such as Nginx to serve static content and reverse proxy everything else to your Node app, which makes it less of an issue since Nginx can be quite happily run as root.

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

EDIT: As your use case requires serving some static content, then you may want to use a web server such as Nginx or Apache to handle the static files, and reverse proxy to another port for your dynamic content. Reverse proxying is quite straightforward with Nginx - here's a sample config file:

编辑:由于您的用例需要提供一些静态内容,因此您可能希望使用诸如 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;
    }
}

This assumes your web app is to be accessible on port 443, and is running on port 8000. If the location matches the /static folder, it is served from /var/www/mysite/static. Otherwise, Nginx hands it off to the running application at port 8000, which might be a Node.js app, or a Python one, or whatever.

这假设您的 Web 应用程序可在端口 443 上访问,并在端口 8000 上运行。如果该位置与 /static 文件夹匹配,则它从 /var/www/mysite/static 提供。否则,Nginx 会将其交给在端口 8000 上运行的应用程序,它可能是一个 Node.js 应用程序,或者一个 Python 应用程序,或者其他任何东西。

This also quite neatly solves your issue since the application will be accessible on port 443, without having to actually bind to that port.

这也非常巧妙地解决了您的问题,因为应用程序可以在端口 443 上访问,而无需实际绑定到该端口。

It should be said that as a general rule of thumb running a service like this as root isn't a good idea. You'd be giving root access to an application which might potentially have vulnerabilities, and to any NPM modules you've pulled in. Putting it behind, for example, Nginx will mean you don't need to run it as root, and Nginx is solid and well-tested, as well as having solid performance and caching capability. In addition, Nginx will usually be faster at serving static content in particular.

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