在使用80端口运行Node.js时的最佳实践(Ubuntu / Linode)[已关闭]
在使用80端口运行Node.js时的最佳实践(Ubuntu / Linode)[已关闭]
我正在在一个云Linux节点上设置我的第一个Node.js服务器,对于Linux管理员的细节我还是比较新手。(顺便说一句,我不打算同时使用Apache。)
一切都安装正确,但我发现除非我使用root登录,否则我无法使用node监听端口80。然而,出于安全原因,我宁愿不要以root身份运行它。
以下是最佳实践:
- 为node设置良好的权限/用户,以保证安全/隔离。
- 在这些限制条件下允许使用端口80。
- 启动node并自动运行。
- 处理发送到控制台的日志信息。
- 其他一般维护和安全问题。
我应该将端口80的流量转发到另一个监听端口吗?
谢谢
在Ubuntu / Linode上运行Node.js时,使用端口80的最佳实践
在Ubuntu / Linode上运行Node.js时,如果想要使用端口80,则需要以root权限运行。然而,以root权限运行Node.js会带来一些安全风险。为了解决这个问题,可以在绑定到端口80后,降低进程权限。
下面是一个示例代码,演示了如何在绑定到端口80后降低进程权限:
function drop_root() {
process.setgid('nobody');
process.setuid('nobody');
}
var process = require('process');
var http = require('http');
var server = http.createServer(function(req, res) {
res.write("Success!");
res.end();
});
server.listen(80, null, null, function() {
console.log('User ID:',process.getuid()+', Group ID:',process.getgid());
drop_root();
console.log('User ID:',process.getuid()+', Group ID:',process.getgid());
});
上述代码首先创建了一个HTTP服务器,监听端口80。然后,在服务器开始监听之后,调用drop_root()函数,将进程的用户和组权限降低为'nobody'。最后,通过调用process.getuid()和process.getgid()来确认进程的用户和组权限是否已经降低成功。
更多详细信息和参考资料可以在这里找到。
通过在绑定端口80后降低进程权限,可以保护端口80的安全性,同时避免以root权限提供服务的安全风险。这是在Ubuntu / Linode上运行Node.js时使用端口80的最佳实践。
在Ubuntu / Linode上运行Node.js时,如果想使用端口80,需要进行一些配置。默认情况下,安全用户没有使用默认HTTP端口80的权限。但是我们不想以root用户的身份运行应用程序。解决方法是给安全用户赋予使用端口80的权限。以下是解决方法:
1. 使用以下命令安装libcap2-bin软件包:
sudo apt-get install libcap2-bin
2. 使用以下命令设置node可执行文件的权限:
sudo setcap cap_net_bind_service=+ep `readlink -f \`which node\``
现在,当你告诉Node应用程序要在端口80上运行时,它将不会报错。这样你就可以通过易于使用的URL(如http://ip:port/)发布网站供访问者使用。
这个解决方法非常简单,但很多人在这里遇到问题。如果你想了解更多细节,可以参考以下链接:
- [https://www.digitalocean.com/community/tutorials/how-to-use-pm2-to-setup-a-node-js-production-environment-on-an-ubuntu-vps#give-safe-user-permission-to-use-port-80](https://www.digitalocean.com/community/tutorials/how-to-use-pm2-to-setup-a-node-js-production-environment-on-an-ubuntu-vps#give-safe-user-permission-to-use-port-80)
- [http://stackoverflow.com/questions/23281895/23281904#23281904](http://stackoverflow.com/questions/23281895/23281904#23281904)
此外,某些情况下类似的解决方法也适用于NGINX等Web服务器,但具体情况取决于服务器的运行方式。如果以root用户身份运行NGINX,则不会出现权限问题。如果以普通用户身份运行并遇到错误,请运行上述命令以给安全用户访问端口的权限,并参考以下链接获取更多信息:
- [http://stackoverflow.com/questions/31369480](http://stackoverflow.com/questions/31369480)
在Ubuntu / Linode上运行Node.js时的最佳实践
当在云实例上运行Node.js时,我使用以下命令将端口80重定向到端口3000:
sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 3000
然后我在端口3000上启动我的Node.js。对端口80的请求将被映射到端口3000。
你还应该编辑你的`/etc/rc.local`文件,并添加那行命令(去掉`sudo`)。这将在机器启动时添加重定向。在`/etc/rc.local`中不需要使用`sudo`,因为该命令在系统启动时以`root`身份运行。
使用`forever`模块来启动你的Node.js。它会确保如果Node.js崩溃,它会重新启动,并将控制台日志重定向到文件中。
将你的Node.js启动脚本添加到你编辑端口重定向的文件`/etc/rc.local`中。这将在系统启动时运行你的Node.js启动脚本。
这不仅适用于Linode,还适用于Digital Ocean、AWS EC2和其他VPS提供商。但是,在基于RedHat的系统中,`/etc/rc.local`是`/ect/rc.d/local`。
通常,对于虚拟专用服务器,"-i eth0"参数可能会有问题。根据需要替换`eth0`。
如果我将我的Node.js启动脚本添加到`/etc/rc.local`中,它会在系统启动时以`root`身份运行吗?那样会破坏端口80重定向的目的。
是的,这是正确的。如果你从`/etc/rc.local`启动你的Node.js脚本,它将以`root`身份运行。然而,安全最佳实践是永远不要以`root`身份运行服务器。
但是我在端口80上运行web服务器,所以在这种情况下web服务器将无法工作。请给予建议。
如果你已经在端口80上运行了一个web服务器,那么你需要配置它作为Node.js后端服务器的反向代理。
这样做会使我的VPN(我在同一个VPS上托管)不起作用。
添加Node.js启动脚本到`/etc/rc.local`文件是什么意思?我只需要添加一个调用脚本的行吗,比如:node server.js
?
请注意,为了使端口重定向工作,目标端口也需要在防火墙上打开。关于在启动时启动一个Node实例,我们只需使用发行版的init脚本/systemd文件,这些文件允许你指定一个用户。
假设我有两个可用的IP,其中一个绑定到端口80上的apache,我该如何将另一个IP添加到上面的命令中?
你需要将`-i eth0`改为`-i eth1`,这将针对第二个接口而不是第一个接口。
如果IP位于子接口(eth0:cp1)中怎么办?
我实际上没有使用过子接口,但我认为它的工作方式应该是一样的。
OP: 有没有办法解决`rc.local`命令以root身份运行的问题?
在我们将Node.js应用程序切换到Elastic Beanstalk之前,我们在应用程序本身中使用`process.setgid()`和`process.setuid()`来降低其权限,以达到一个专门创建的`nodejs`系统用户的权限。
发送到:80的套接字似乎没有被转发到:3000。请帮忙解决。
确保你正确使用了`-i`参数,或者将其删除。
“将Node.js脚本添加到`/etc/rc.local`”是什么意思?请告诉我我应该写什么,我还在使用forever。
当重定向时,是否需要通过`ufw`允许特定端口?根据你的例子,我注意到只有在通过防火墙允许3000端口(`ufw allow 3000/tcp`)时才起作用,但这也允许任何人通过该端口访问;因此,外部人员可以通过域名(默认为80端口)、域名:80、域名:3000和IP地址(例如123.456.789.012:80/3000)访问页面。我认为期望是允许在80端口上内部提供TCP流量,并由3000端口进行服务;所以对外部用户关闭所有端口,除了80端口。
我想我刚刚重复了你之前说的话,对吗?有可能在内部进行端口转发吗?
如果我使用这个解决方案,以后我想取消这个流量重定向,该怎么做?
太棒了,解决方案的第二行在我的一个服务器上完美运行。谢谢!
除了将iptables更改添加到rc.local中,还可以编辑`/etc/network/interfaces`,添加以下两行:`pre-up iptables-restore < /etc/iptables.rules post-down iptables-save > /etc/iptables.rules`
在无线笔记本上,可以省略`-i eth0`吗?我尝试了这个,但仍然不起作用:`iptables -F iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 5000`
如何撤销这个命令?
这种解决方案很糟糕,你正在加载不必要的流量到你的内核中。所有的数据包都是从一个缓冲区复制到另一个缓冲区,你正在浪费资源。一个更好的选择是在初始化时将Node进程的权限降级为一个特殊创建的`nodejs`系统用户。
如果你正在使用AWS并且使用ELB,则只需将ELB端口转发到正确的实例端口。如果你在不同端口上运行多个应用程序,这种解决方案将不起作用。
小提示,在`/etc/rc.local`文件中有一行提示:`请注意,您必须运行“chmod +x /etc/rc.d/rc.local”以确保在启动时执行此脚本。`我已经添加了这一行,但是没有运行`chmod`命令,当机器重新启动时它没有更新。