侦听大多数端口时出现Node.js EACCES错误

jwe*_*ner 231 http permission-denied node.js

我正在测试一个应用程序(希望在heroku上运行,但在本地也有问题).运行http.Server.listen()时它会给我一个EACCES错误 - 但它只发生在某些端口上.

所以,我在本地运行:

joe@joebuntu:~$ node
> var h = require('http').createServer();
> h.listen(900);
Error: EACCES, Permission denied
    at Server._doListen (net.js:1062:5)
    at net.js:1033:14
    at Object.lookup (dns.js:132:45)
    at Server.listen (net.js:1027:20)
    at [object Context]:1:3
    at Interface.<anonymous> (repl.js:150:22)
    at Interface.emit (events.js:42:17)
    at Interface._onLine (readline.js:132:10)
    at Interface._line (readline.js:387:8)
    at Interface._ttyWrite (readline.js:564:14)
Run Code Online (Sandbox Code Playgroud)

我没有在端口900上运行任何东西(或者我试过的其他20个端口),所以这应该有效.奇怪的是它确实可以在某些端口上运行.例如,端口3000完美运行.

什么会导致这个?

更新1:

我发现在我的本地计算机上,EACCES错误即将发生,因为我必须以root身份运行节点才能绑定到那些特定端口.我不知道为什么会这样,但使用sudo修复它.但是,这并没有解释我如何在Heroku上修复它.没有办法在Heroku上以root身份运行,那么我怎样才能在端口80上侦听?

Ben*_*ber 320

在您的工作站上运行

作为一般规则,在没有root权限的情况下运行的进程无法绑定到1024以下的端口.

因此,尝试更高端口,或通过提升权限运行sudo.使用process.setgid和绑定到低端口后,可以降级权限process.setuid.

在heroku上运行

在heroku上运行应用程序时,必须使用PORT环境变量中指定的端口.

请参见http://devcenter.heroku.com/articles/node-js

const server = require('http').createServer();
const port = process.env.PORT || 3000;

server.listen(port, function() {
  console.log('Listening on ' + port);
});
Run Code Online (Sandbox Code Playgroud)

  • 是.您只能收听我们在$ PORT上告诉您的端口我们负责将80或443路由到您的端口.当我们移动你的dyno时,实际端口会一直变化.目前,我们只支持从80和443公开路由. (12认同)
  • 这是否意味着我必须使用Heroku提供的端口,然后他们会在后台做一些魔术操作以将其传输到80端口?如果我不想在端口80上运行某些东西怎么办? (3认同)
  • 为什么您希望您的应用程序在与 http 和 https 不同的端口上运行? (2认同)

小智 169

非特权用户(非root用户)无法在1024以下的端口上打开侦听套接字.

  • 我不喜欢这个,我不想在使用node(实际上是gulp)运行快速服务器时需要`sudo`.所以没有意义 (6认同)
  • Upvoted - 这是一个很好的一般规则,但也有例外,例如Linux上的"功能". (4认同)
  • @blamb然后使用[MeetMehta的解决方案](http://stackoverflow.com/a/23281417/1028230); ^) (4认同)
  • 你刚刚节省了我几个小时的调试时间 我不知道那件事. (3认同)

Mee*_*hta 94

查看此参考链接:

授予安全用户权限以使用端口80

请记住,我们不希望以root用户身份运行您的应用程序,但有一个障碍:您的安全用户无权使用默认HTTP端口(80).您的目标是能够通过导航到易于使用的URL来发布访问者可以使用的网站 http://ip:port/

不幸的是,除非您以root身份登录,否则通常必须使用类似的URL http://ip:port- 其中端口号> 1024.

很多人都被困在这里,但解决方案很简单.有一些选择,但这是我喜欢的.输入以下命令:

sudo apt-get install libcap2-bin
sudo setcap cap_net_bind_service=+ep `readlink -f \`which node\``
Run Code Online (Sandbox Code Playgroud)

现在,当您告诉Node应用程序您希望它在端口80上运行时,它不会抱怨.

  • 为什么不是这个答案 (4认同)
  • 这绝对是最好的解决方案. (3认同)

Nig*_*ist 58

#视窗

另一个原因 - 也许您的端口因某些原因被排除在外

因此,尝试在管理员权限下打开 CMD(命令行)并运行:

  1. net stop winnat
  2. net start winnat

就我而言,这就足够了。

在这里找到的解决方案:https : //medium.com/@Bartleby/ports-are-not-available-listen-tcp-0-0-0-0-3000-165892441b9d

  • 这解决了我的问题,谢谢。但是,谁能解释一下突然出现这个问题的原因是什么? (20认同)
  • 这个解决方案对我来说非常有效。谢谢你! (4认同)
  • 在 Windows 11 上为我工作,非常感谢! (2认同)

Rid*_*lik 53

如果您使用的是Windows . 您应该尝试重新启动Windows NAT 驱动程序服务

管理员身份打开命令提示符并运行

net stop winnat
Run Code Online (Sandbox Code Playgroud)

然后

net start winnat
Run Code Online (Sandbox Code Playgroud)

就是这样。

发生这种情况是因为我安装了Nord VPN,它会自动盯着 Windows。


小智 42

在 Windows 系统上,重新启动服务“主机网络服务”,解决了该问题。

  • 这需要更多的支持!谢谢 - 有时我遇到这个问题并且总是不得不重新启动整个机器。 (2认同)
  • 这为我解决了这个问题!谁能帮助我理解为什么以及如何? (2认同)
  • 终于有一个比重启更好的答案了! (2认同)

小智 15

剧透警报:这个答案可能看起来有点好笑。

我花了 10 多分钟来找出系统中出现此错误的根本原因。我PORT=2000;在我的 .env 文件中使用了这个:

希望你已经发现了。我在声明端口号后使用了分号:'( 我删除了额外的符号,它开始工作。

我知道这可能不是这个问题的答案,但希望它可以帮助其他遇到同样问题的人。


ele*_*ven 9

另一种方法是进行端口重定向:

sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 900 -j REDIRECT --to-port 3000
Run Code Online (Sandbox Code Playgroud)

并在> 1024端口上运行您的服务器:

require('http').createServer().listen(3000);
Run Code Online (Sandbox Code Playgroud)

ps顺便说一句,对于https(443)端口也可以这样做.


Fus*_*ieb 6

我有一个类似的问题,它拒绝在端口 8080 上运行,但也有任何其他端口。

事实证明,这是因为env.local它读取的文件在变量名称后面包含注释,例如:

PORT=8080 # The port the server runs at
Run Code Online (Sandbox Code Playgroud)

它像这样解释它,试图使用端口“ 8080 # The port the server runs at”,这显然是一个无效端口(-1)。删除评论完全解决了它。

顺便说一下,使用 Windows 10 和 Git Bash。


我知道这并不完全是这里描述的问题,但它可能会对那里的人有所帮助。我在这个问题上寻找答案,所以......也许?


Dil*_*ana 5

我的天啊!!在我的情况下,我正在做....listen(ip, port)而不是...listen(port, ip)抛出错误消息:Error: listen EACCES localhost

我使用的端口号 >= 3000,甚至尝试使用管理员访问。什么都没解决。然后仔细再看,我注意到了这个问题。将其更改为...listen(port, ip),一切开始正常!

如果它对其他人有用,只需调用它...