在我的开发盒上有这种限制是非常令人讨厌的,因为除了我之外再也没有其他用户了。

我知道一些标准的变通办法,但没有一个能完全满足我的要求:

authbind (Debian测试中的版本,1.0,仅支持IPv4) 使用iptables REDIRECT目标将低端口重定向到高端口(iptables的IPv6版本ip6tables尚未实现“nat”表) sudo(作为根是我试图避免的) SELinux(或类似的)。(这只是我的开发框,我不想引入很多额外的复杂性。)

是否有一些简单的sysctl变量允许非根进程绑定到Linux上的“特权”端口(端口小于1024),或者我只是运气不好?

编辑:在某些情况下,您可以使用功能来做到这一点。


当前回答

Linux支持支持更细粒度权限的功能,而不仅仅是“此应用程序以根用户身份运行”。其中一个功能是CAP_NET_BIND_SERVICE,它是关于绑定到特权端口(<1024)的。

不幸的是,我不知道如何利用它来运行一个应用程序作为非根,同时仍然给它CAP_NET_BIND_SERVICE(可能使用setcap,但肯定有一个现有的解决方案)。

其他回答

还有一种“djb方式”。您可以使用此方法以运行在tcpserver下任何端口上的根用户身份启动您的进程,然后在进程启动后,它将把进程的控制权立即交给您指定的用户。

#!/bin/sh

UID=$(id -u username)
GID=$(id -g username)
exec tcpserver -u "${UID}" -g "${GID}" -RHl0 0 port /path/to/binary &

更多信息,请参见:http://thedjbway.b0llix.net/daemontools/uidgid.html

您可以进行端口重定向。这就是我为运行在Linux机器上的Silverlight策略服务器所做的工作

iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 943 -j REDIRECT --to-port 1300

文件功能并不理想,因为它们可能在包更新后失效。

恕我直言,理想的解决方案应该是能够创建具有可继承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"

我的“标准解决方案”使用socat作为用户空间重定向器:

socat tcp6-listen:80,fork tcp6:8080

注意,这不会扩展,分叉是昂贵的,但这是socat工作的方式。

端口重定向对我们来说是最有意义的,但我们遇到了一个问题,我们的应用程序将在本地解决一个url,也需要重新路由;(意思是你在狂欢)。

这也将允许您在访问本地机器上的url时被重定向。

iptables -A PREROUTING -t nat -p tcp --dport 80 -j REDIRECT --to-port 8080
iptables -A OUTPUT -t nat -p tcp --dport 80 -j REDIRECT --to-port 8080