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

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

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"

其他回答

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

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

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

socat tcp6-listen:80,fork tcp6:8080

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

或者修补内核并删除检查。

(最后的选择,不推荐)。

在net/ipv4/af_inet.c中,删除读取的两行

      if (snum && snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
              goto out;

内核将不再检查特权端口。

出于某种原因,没有人提到降低sysctl net.ipv4。Ip_unprivileged_port_start到您需要的值。 示例:我们需要将应用程序绑定到443端口。

sysctl net.ipv4.ip_unprivileged_port_start=443

有些人可能会说,存在潜在的安全问题:非特权用户现在可能绑定到其他特权端口(444-1024)。 但是你可以用iptables通过阻塞其他端口轻松解决这个问题:

iptables -I INPUT -p tcp --dport 444:1024 -j DROP
iptables -I INPUT -p udp --dport 444:1024 -j DROP

与其他方法的比较。这个方法:

from some point is (IMO) even more secure than setting CAP_NET_BIND_SERVICE/setuid, since an application doesn't setuid at all, even partly (capabilities actually are). For example, to catch a coredump of capability-enabled application you will need to change sysctl fs.suid_dumpable (which leads to another potential security problems) Also, when CAP/suid is set, /proc/PID directory is owned by root, so your non-root user will not have full information/control of running process, for example, user will not be able (in common case) to determine which connections belong to application via /proc/PID/fd/ (netstat -aptn | grep PID). has security disadvantage: while your app (or any app that uses ports 443-1024) is down for some reason, another app could take the port. But this problem could also be applied to CAP/suid (in case you set it on interpreter, e.g. java/nodejs) and iptables-redirect. Use systemd-socket method to exclude this problem. Use authbind method to only allow special user binding. doesn't require setting CAP/suid every time you deploy new version of application. doesn't require application support/modification, like systemd-socket method. doesn't require kernel rebuild (if running version supports this sysctl setting) doesn't do LD_PRELOAD like authbind/privbind method, this could potentially affect performance, security, behavior (does it? haven't tested). In the rest authbind is really flexible and secure method. over-performs iptables REDIRECT/DNAT method, since it doesn't require address translation, connection state tracking, etc. This only noticeable on high-load systems.

根据具体情况,我将在sysctl、CAP、authbind和iptables-redirect之间进行选择。我们有这么多选择真是太好了。

在启动时:

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

然后可以绑定到您转发的端口。