Node.js + Express:应用程序不会开始侦听端口80

Vit*_*aly 38 port amazon-ec2 node.js express

我创建并启动了这样的应用程序:

express -s -t ejs
npm install express
npm install ejs
node app.js
Run Code Online (Sandbox Code Playgroud)

它的工作原理(在3000端口).但是当我将端口更改为80时,则运行node app.js输出:

node.js:198
throw e; // process.nextTick error, or 'error' event on first tick
          ^
TypeError: Cannot call method 'getsockname' of null
at HTTPServer.address (net.js:746:23)
at Object.<anonymous> (/var/www/thorous/app.js:35:67)
at Module._compile (module.js:432:26)
at Object..js (module.js:450:10)
at Module.load (module.js:351:31)
at Function._load (module.js:310:12)
at Array.<anonymous> (module.js:470:10)
at EventEmitter._tickCallback (node.js:190:26)
Run Code Online (Sandbox Code Playgroud)

这也适用于我的笔记本电脑,但不适用于我的Amazon EC2实例,其中端口80已打开.可以弄清楚什么是错的.有小费吗?

Mic*_*nor 80

如果您真的想这样做,您可以将端口80上的流量转发到3000.

sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 3000
Run Code Online (Sandbox Code Playgroud)

  • 这个命令打倒了我的整个数字海洋服务器...只是想把它放在那里供别人看 (3认同)
  • 您可能有另一个进程在该端口上运行,当您将 80 重定向到 3000 时,该进程被破坏。 (3认同)

Tho*_*itz 64

您是否以root身份启动应用程序?因为较低的端口号需要root权限.也许sudo节点app.js有效?

但是,你不应该使用root权限在端口80上运行任何node.js应用程序!决不!

我的建议是在前面运行nginx作为在端口上运行的node.js应用程序的反向代理,例如3000

  • 这不仅适用于节点.建议不要以root身份运行任何服务器软件.如果必须,因为您要使用特权端口,该进程将丢弃特权并将该端口上的所有传入流量"转发"到在较小的用户上运行的相应进程.这是因为没有一个程序是完美的.每个软件都有错误,也许还有安全问题.如果攻击者可以利用此类错误并注入代码 - 这将在用户运行此过程时执行.因此,如果您的进程以root身份运行,攻击者可以在您的计算机上执行任何操作 (9认同)
  • 你能详细说明为什么不在端口80上以root身份运行node.js应用程序?我好奇(一个新手js开发). (7认同)
  • @trysis因为,像任何其他进程一样,apache需要root权限才能侦听特权端口80.但是它会立即创建"工作进程"并将其权限丢给较低权限的用户和组,然后转发所有传入的请求该端口到其工作进程.但是节点是一个单一的过程 - 你可以把它看作是一个apache的工作进程.如果要在80上运行节点,整个过程 - 每个可能的指令 - 将以root身份运行.所以它有点像nginx(80) - > node(3000) (5认同)
  • 在这种情况下,将nginx作为反向代理运行会有点过分。我建议使用`iptables`进行端口转发,除非Express应用程序之前需要其他nginx功能。 (2认同)
  • @ThomasFritz为什么我们通常在端口80上运行Apache,如果你说我们不应该在那里运行Node? (2认同)

Coo*_*J86 6

保持愚蠢简单:

  • setcap
  • systemd
  • 虚拟专用网

在磁盘持久的普通 VPS(例如Digital OceanLinodeVultrScaleway)上,使用“setcap”。这将允许非 root 用户绑定到特权端口。

sudo setcap 'cap_net_bind_service=+ep' $(which node)
Run Code Online (Sandbox Code Playgroud)

多田!现在您可以node ./server.js --port 80以普通用户身份运行了!

旁白

您还可以使用systemd来停止和启动您的服务。由于systemd有时是pita,我用Go编写了一个包装脚本,这使得部署节点项目变得非常容易:

# Install
curl https://webinstall.dev/serviceman | bash
Run Code Online (Sandbox Code Playgroud)
# Use
cd ./my/node/project
sudo serviceman --username $(whoami) add npm start
Run Code Online (Sandbox Code Playgroud)

或者,如果您的服务器未被称为“server.js”(事实上的标准),或其他选项:

cd ./my/node/project
sudo serviceman --username $(whoami) add node ./my-server-thing.js -- --my-options
Run Code Online (Sandbox Code Playgroud)

所做的就是systemd使用合理的默认值为您创建文件。我建议您也查看systemd文档,但它有点难以理解,并且可能有更多的混乱和糟糕的教程,而不是简单的和其他好的教程。

临时实例(即 EC2)不适用于长时间运行的服务器

通常,当人们使用 EC2 时,是因为他们不关心单个实例正常运行时间的可靠性——他们想要一个“可扩展”的架构,而不是持久的架构。

在大多数情况下,实际上并不打算让虚拟化服务器以任何方式持续存在。在这些类型的“短暂”(临时)环境中,“重启”与从头重新安装大致相同。

您不是“设置服务器”而是“部署映像”。您登录此类服务器的唯一原因是对您正在创建的图像进行原型设计或调试。

“磁盘”是不稳定的,IP 地址是浮动的,每次启动时图像的行为都相同。您通常也不会使用传统意义上的用户帐户概念。

因此:虽然通常情况下,您不应该以 root 身份运行服务,但您通常使用易失性虚拟化的情况类型……但这并不重要。您只有一个服务,一个用户帐户,并且一旦实例失败或以其他方式“重新启动”(或者启动映像的新实例),您就会重新拥有一个全新的系统(这确实意味着任何漏洞仍然存在)。

防火墙:临时 vs VPS

像 EC2 这样的东西通常只用于私有,而不是面向公众。这些是“云服务”系统。您需要使用十几种不同的服务并自动扩展。因此,您将使用负载均衡器服务将端口转发到您的 EC2 组。通常,实例的默认防火墙会拒绝所有公共网络流量。您必须进入防火墙管理并确保您打算使用的端口实际上是打开的。

有时 VPS 提供商有“企业”防火墙配置器,但更常见的是,您只能获得对虚拟机的原始访问权限,因为只有您实际监听的端口才能首先访问外部世界(默认情况下,他们通常不会访问)运行随机服务),您可能无法从防火墙中获得任何额外的好处。当然是个好主意,但不是必须做你需要做的事情。

不要将 EC2 用作 VPS

您上面的用例可能更适合传统 VPS 服务(如上所述: Digital OceanLinodeVultrScaleway等),这些服务更易于使用,而且入门的管理麻烦也少得多。您所需要的只是一点点 bash CLI 专业知识。

而且,作为额外的奖励,您不必猜测成本是多少。他们用简单的$/month而不是 ¢/cpu/hour/gb/internal-network/external-network/etc告诉你- 所以当出现问题时,你会通过电子邮件或管理控制台收到警告,而不是意外的账单6,527 美元。

底线:如果您选择使用 EC2 并且您不是拥有会计人员的“DevOps”专家……您会遇到困难。