如何在端口80上运行Node.js?

88

我的目标是在80端口上运行Node.js。这是因为我发现某些网络会阻止Node.js从任何其他端口发送流量。

看起来最好的方法是通过Node.js代理Apache。我已经尝试使用node-http-proxy来实现,但是没有成功。

我正在使用的代码在此处:

var util = require('util'),
    http = require('http'),
    httpProxy = require('http-proxy');

httpProxy.createServer(9000, 'localhost').listen(80);

http.createServer(function (req, res) {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.write('request successfully proxied to: ' + req.url + '\n' + JSON.stringify(req.headers, true, 2));
  res.end();
}).listen(9000);

但我一直收到“地址正在使用”的错误,端口为80。我一定做错了什么。

我如何通过node-http-proxy代理Apache来运行node.js?这样会使我能够在端口80上运行node.js吗?node-http-proxy是实现此目的的最佳方式吗?

谢谢。

9个回答

132

将您的应用程序运行在高端口8080或其他端口上,然后继续操作。

sudo iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 8080

如果您没有使用Nginx或Apache


2
还知道如何撤销这个操作会很有帮助。我认为“--to-port 80”不是完美的解决方案。它仍然需要处理这个绑定。 - Lilian A. Moraru
7
就这样,Nginx 已被淘汰。 - user636044
14
要撤销此操作:sudo iptables -D PREROUTING -t nat -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 8080(基本上将-A更改为-D即可。就这样) - rckehoe
如何在这里设置特定的IP地址? - jonathancardoso
你怎么撤销这个操作?谢谢。 - jofftiquez
显示剩余2条评论

66

最简单的解决方案: 安全地配置您的Node应用程序在80端口上运行

  • sudo apt-get install libcap2-bin
  • sudo setcap cap_net_bind_service=+ep /path/to/node
  • 完成!

为什么我喜欢它?

  • 您不必使用Apache或Nginx
  • 您不必以root身份运行应用程序
  • 您不需要转发端口(并在每次启动机器时处理)

参考链接:https://www.digitalocean.com/community/tutorials/how-to-use-pm2-to-setup-a-node-js-production-environment-on-an-ubuntu-vps(关于如何在云主机上设置您的Node应用程序的绝佳文章)。


1
赞赏你不仅提供了最优雅的解决方案,还提供了一个合法的参考链接。 - Gor
这正是我所需要的。我花了一段时间苦思冥想,试图弄清楚为什么我可以在节点上启动我的Express HTTP服务器,但除了80端口之外的所有端口都可以。 - nick
太好了!只需要记得如果升级Node(例如使用nvm),就需要再次执行此操作。 - Jackson
除了 Node 之外,这对其他平台也很有用。 - Charles Wood
它对我没有用。我在Mac上执行了sudo setcap cap_net_bind_service=+ep /usr/bin/nodejs命令。当我执行netstat -tlpn时,它仍然显示apache2在80端口和nodejs在8000端口。我做错了什么? - codeinprogress
@codeinprogress 你还需要告诉你的 Node 应用程序在端口 80 上运行。 - Kyle Chadha

31

你需要做的是为运行的服务器拥有2个IP地址。Apache绑定到80端口的是一个IP,而Node.js绑定到80端口的是另一个IP。

通过使用Node的listen指令有两个值,例如:.listen(80, NODEJS_IP或DNS名称);

其他一些建议:

我不建议将Apache与Node.js一起使用,因为它不是事件驱动的,这并不推荐。我建议尝试使用NGINX,因为它与Node更加兼容。


@PaulM 谢谢。我该如何将辅助 IP 绑定到端口 80 和 Node.js,而不是 Apache? - Kit
使用您的DNS,例如www.domain.com对应一个IP地址,chat.domain.com对应另一个IP地址。在Apache中监听第一个IP地址:Listen vvv.xxx.yyy.zzz:80。然后使用Node执行.listen(80, chat.domain.com)。这是我正在使用的设置,我没有遇到任何公司防火墙等问题。 - PaulM
1
我不建议在node中使用nginx。Nginx不支持HTTP 1.1,这意味着您将无法执行某些WebSocket操作。当您使用node.js时,我认为您会想要使用这个真正快速的东西;) - Van Coding
2
@FlashFan,我能在我的网站上使用Chrome来进行WebSocket操作,有什么需要详细说明的吗? - PaulM
@PaulM - 我在尝试将Apache绑定到特定IP时遇到了麻烦。我在这里提出了问题:http://serverfault.com/questions/273143/binding-apache-to-specific-ip-address/273155#273155 当您这样做时是否遇到任何问题? - Kit
我已回答。在apache.conf文件中,您只需要一个Listen实例。您只需要将一个IP绑定到apache。 - PaulM

21

目前不建议在80端口上运行node,因为这需要将node作为root用户运行。

你对apache有多么依赖?通过nginx代理node是一种经过验证的解决方案,可以使用类似于以下nginx配置:

upstream node_cluster {
    ip_hash;   
    server 127.0.0.1:8000;
    server 127.0.0.1:8001;
    server 127.0.0.1:8002;
}

server {
    listen 0.0.0.0:80;
    server_name foo;
    access_log /var/log/nginx/foo.log;

    location / {
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $http_host;

      proxy_pass http://node_cluster/;
      proxy_redirect off;
    }
}

Nginx文档:

http://wiki.nginx.org/HttpProxyModule

http://wiki.nginx.org/HttpUpstreamModule


4
很多人在80端口上运行节点。通过nginx代理需要一些开销。同时你不需要root权限来在80端口上运行。查看这里获取更多信息:http://comments.gmane.org/gmane.comp.lang.javascript.nodejs/8959 。我自己也没有使用root来运行节点。 - PaulM
谢谢,Waquo。我正在看我的选项。Nginx 可能是前进的道路。 - Kit
看看dryprogrammers的答案,了解如何在不使用root权限的情况下在端口80上运行Node。 - user636044
这个答案让我感觉我可以从同一个服务器和IP为Node和PHP应用提供服务,为每个应用使用不同的端口,但我对nginx并不是很熟悉,不能确定它是否真的可行... - Loupax
为了在80端口上进行测试,我停止了apache2并需要以SUDO身份运行。普通用户无法使用端口80调用节点,但root可以。感谢提供所需信息。 - Sergio Abreu

9
您的代码看起来像是创建了一个基于Node的代理,从端口80到端口9000,然后在端口9000上创建了一个基于Node的HTTP服务器。(即 Node:80 -> Node:9000) 当您启动Node时,会出现“地址已被使用”的错误,因为Apache已经在使用端口80。如果您想要使用Apache进行代理,必须在不同的端口(比如9000)上使用Node,并使Apache在端口80上监听并将请求转发到Node的9000端口。(即 Apache:80 -> Node:9000) 看起来您正在使用的库是相反的:使用Node作为代理并将请求转发到Apache。在这种情况下,您必须配置Apache在另一个端口而不是80端口运行。(即 Node:80 -> Apache:9000) 您最终想要做的是 Node:80 -> Apache:9000 还是 Apache:9000 -> Node:80
评论后编辑: 如果您想要做 Apache:80 -> Node:9000,您可以在Apache上使用mod_proxy,并使用ProxyPass/ProxyPassReverse指令,类似于:
ProxyPass /nodeurls/ http://localhost:9000/
ProxyPassReverse /nodeurls/ http://localhost:9000/  

nodeurls是您希望Apache转发给Node的URL系列。


谢谢。我不太确定。抱歉!我想让Node在Apache:80上运行:所以.. Node:9000->Apache:80。不太确定这是否正确。 - Kit
如果您想在端口80上运行Apache,则必须在另一个端口(比如9000)上运行Node。在这种情况下,您必须配置Apache将一些请求转发到Node。我会将其写成Apache:80 -> Node:9000,以便继续我上面所写的内容。 - nicolaskruchten
啊,好的。我明白了。我该如何让Apache将一些请求转发给Node呢? - Kit
看一下我的修改,你需要安装一个模块并进行配置。 - nicolaskruchten
1
我认为你在第一行的意思是 Apache:80 -> Node:9000 而不是 Node:80 -> Node:9000 - Pratik Khadloya

7

如果你是非root用户,在Unix系统中你无法运行或绑定到低于1024的端口。要允许非root用户在低于1024的端口上运行节点,请使用此命令。

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

这对我有用。有人能解释一下它在做什么吗?我想至少要理解它,以便在需要时可以撤销它。 - robm

3

0

我遇到了相同的问题,我只是把端口改成了8080,然后它就可以了。

httpsServer.listen(8080, () =>
    console.log(chalk.rgb(208, 60, 240)(`Server listening on port: 8080`))
  );

-6

如果你只是在开发环境模式下

你可以su root,然后

node index.js./node_modules/coffee-script/bin/coffee index.coffee


3
出于安全考虑,我强烈建议不要使用 root 权限运行服务器,我并非网络管理员。 - nick

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