在我的开发盒上有这种限制是非常令人讨厌的,因为除了我之外再也没有其他用户了。
我知道一些标准的变通办法,但没有一个能完全满足我的要求:
authbind (Debian测试中的版本,1.0,仅支持IPv4)
使用iptables REDIRECT目标将低端口重定向到高端口(iptables的IPv6版本ip6tables尚未实现“nat”表)
sudo(作为根是我试图避免的)
SELinux(或类似的)。(这只是我的开发框,我不想引入很多额外的复杂性。)
是否有一些简单的sysctl变量允许非根进程绑定到Linux上的“特权”端口(端口小于1024),或者我只是运气不好?
编辑:在某些情况下,您可以使用功能来做到这一点。
文件功能并不理想,因为它们可能在包更新后失效。
恕我直言,理想的解决方案应该是能够创建具有可继承CAP_NET_BIND_SERVICE集的shell。
这里有一个有点复杂的方法:
sg $DAEMONUSER "capsh --keep=1 --uid=`id -u $DAEMONUSER` \
--caps='cap_net_bind_service+pei' -- \
YOUR_COMMAND_GOES_HERE"
capsh实用程序可以在Debian/Ubuntu发行版的libcap2-bin包中找到。事情是这样的:
sg将生效的组ID修改为守护用户的组ID。这是必要的,因为capsh会使GID保持不变,而我们肯定不想要它。
设置位“保持UID更改的能力”。
修改UID为$DAEMONUSER
删除所有的大写(此时所有的大写仍然存在,因为——keep=1),除了可继承的cap_net_bind_service
执行命令(“——”是分隔符)
结果是一个具有指定用户和组以及cap_net_bind_service特权的进程。
例如,ejabberd启动脚本中的一行:
sg $EJABBERDUSER "capsh --keep=1 --uid=`id -u $EJABBERDUSER` --caps='cap_net_bind_service+pei' -- $EJABBERD --noshell -detached"
好的,感谢那些指出系统和CAP_NET_BIND_SERVICE功能的人。如果您有一个最新的内核,确实可以使用它来以非root身份启动服务,但绑定低端口。简单的回答是:
setcap 'cap_net_bind_service=+ep' /path/to/program
然后在任何程序执行之后,它都将具有CAP_NET_BIND_SERVICE能力。Setcap在debian包libcap2-bin中。
现在要注意的是:
You will need at least a 2.6.24 kernel
This won't work if your file is a script. (i.e. uses a #! line to launch an interpreter). In this case, as far I as understand, you'd have to apply the capability to the interpreter executable itself, which of course is a security nightmare, since any program using that interpreter will have the capability. I wasn't able to find any clean, easy way to work around this problem.
Linux will disable LD_LIBRARY_PATH on any program that has elevated privileges like setcap or suid. So if your program uses its own .../lib/, you might have to look into another option like port forwarding.
资源:
能力(7)手册页。如果您打算在生产环境中使用功能,请仔细阅读这篇文章。这里详细介绍了如何在exec()调用之间继承功能的一些非常棘手的细节。
Setcap手册页
“在GNU/Linux上绑定1024以下的端口,没有根”:第一次让我想到setcap的文档。
注意:RHEL首次在v6中添加了这个功能。