【问题标题】:Node.js + Express: app won't start listening on port 80Node.js + Express:应用程序不会开始监听端口 80
【发布时间】:2011-12-17 06:59:39
【问题描述】:

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

express -s -t ejs
npm install express
npm install ejs
node app.js

它可以工作(在端口 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)

这也适用于我的笔记本电脑,但不适用于我的 Amazon EC2 实例,其中端口 80 是开放的。 可以弄清楚是什么问题。有什么建议吗?

【问题讨论】:

  • 这是一个可怕的错误信息。

标签: node.js amazon-ec2 port express


【解决方案1】:

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

sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 3000

【讨论】:

  • 这太棒了!我能够解决问题!
  • 没有 nginx 或其他代理解决方案的漂亮而干净的答案!
  • 小心使用这个命令。如果您在服务器中以 root 身份登录,这会将您所有域上的流量转发到端口 3000。
  • 这个命令关闭了我的整个 digitalocean 服务器......只是想把它放在那里让其他人看到
  • 您可能在该端口上运行了另一个进程,当您将 80 重定向到 3000 时该进程被破坏。
【解决方案2】:

您是否以 root 身份启动您的应用程序?因为较低的端口号需要 root 权限。 也许 sudo node app.js 可以工作?

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

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

【讨论】:

  • 您能否详细说明为什么不在端口 80 上以 root 身份运行 node.js 应用程序?我很好奇(一个新手 js 开发者)。
  • 这并不只适用于节点。不建议以 root 身份运行任何服务器软件。如果您必须这样做,因为您想使用特权端口,该进程会放弃特权并将该端口上的所有传入流量“转发”到在较低特权用户上运行的相应进程。这是因为没有程序是完美的。每个软件都有错误,也许还有安全问题。如果攻击者可以利用此类错误并注入代码 - 这将在用户运行此进程时执行。因此,如果您的进程以 root 身份运行,则攻击者可以在您的计算机上执行任何操作。
  • 在这种情况下,将nginx 作为反向代理运行有点矫枉过正。我建议使用iptables 进行端口转发,除非在 Express 应用程序前面需要额外的 nginx 功能。
  • @ThomasFritz 如果您说我们不应该在那里运行 Node,为什么我们通常在端口 80 上运行 Apache?
  • @trysis 因为,与任何其他进程一样,apache 需要 root 权限才能监听特权端口 80。但它会立即创建“工作进程”并将其特权放弃给特权较低的用户,并且组,然后将该端口上的所有传入请求转发到其工作进程。但是node是一个单一的进程——你可以把它想象成apache的这样一个工作进程。如果您想在 80 上运行节点,则整个过程(每条可能的指令)都将以 root 身份运行。所以它有点类似于 nginx(80) --> node(3000)
【解决方案3】:

保持简单:

  • setcap
  • systemd
  • VPS

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

sudo setcap 'cap_net_bind_service=+ep' $(which node)

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

旁白

您也可以使用systemd 来停止和启动您的服务。因为systemd 有时是一个 p.i.t.a.,所以我写了一个 wrapper script in Go,它使得部署节点项目变得非常容易:

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

或者,如果您的服务器不称为“server.js”(事实上的标准),或者额外的选项:

cd ./my/node/project
sudo serviceman --username $(whoami) add node ./my-server-thing.js -- --my-options

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

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

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

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

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

“磁盘”是易变的,IP 地址是浮动的,映像在每次启动时都表现相同。您通常也不会使用传统意义上的用户帐户概念。

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

防火墙:临时 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”专家,并且有会计人员......您将很难过。

【讨论】:

    【解决方案4】:

    也许之前在端口 80 上运行了其他东西?

    也许做一个端口扫描并确认它没有被使用?

    nc -z <<your IP>> 80
    

    【讨论】:

    • 我什么都想不出来。这是一个全新的实例,安装了 node.js 副本并运行了 mongodb 服务器。 nc 什么也没返回。
    猜你喜欢
    • 2020-06-07
    • 1970-01-01
    • 2013-04-07
    • 1970-01-01
    • 2012-05-17
    • 2018-03-27
    • 1970-01-01
    • 2016-05-05
    • 1970-01-01
    相关资源
    最近更新 更多