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

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

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

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

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


当前回答

由于OP只是开发/测试,不那么圆滑的解决方案可能会有帮助:

可以在脚本解释器上使用Setcap来为脚本授予功能。如果全局解释器二进制文件上的setcaps是不可接受的,那么就对二进制文件做一个本地副本(任何用户都可以),并在这个副本上获取root到setcap。Python2(至少)使用脚本开发树中的解释器的本地副本正常工作。不需要suid,因此根用户可以控制用户可以访问哪些功能。

如果你需要跟踪解释器的系统范围的更新,可以使用下面这样的shell脚本来运行你的脚本:

#!/bin/sh
#
#  Watch for updates to the Python2 interpreter

PRG=python_net_raw
PRG_ORIG=/usr/bin/python2.7

cmp $PRG_ORIG $PRG || {
    echo ""
    echo "***** $PRG_ORIG has been updated *****"
    echo "Run the following commands to refresh $PRG:"
    echo ""
    echo "    $ cp $PRG_ORIG $PRG"
    echo "    # setcap cap_net_raw+ep $PRG"
    echo ""
    exit
}

./$PRG $*

其他回答

2015年9月:

ip6tables现在支持IPV6 NAT: http://www.netfilter.org/projects/iptables/files/changes-iptables-1.4.17.txt

您将需要内核3.7+

证明:

[09:09:23] root@X:~ ip6tables -t nat -vnL
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 REDIRECT   tcp      eth0   *       ::/0                 ::/0                 tcp dpt:80 redir ports 8080
    0     0 REDIRECT   tcp      eth0   *       ::/0                 ::/0                 tcp dpt:443 redir ports 1443

Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain OUTPUT (policy ACCEPT 6148 packets, 534K bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain POSTROUTING (policy ACCEPT 6148 packets, 534K bytes)
 pkts bytes target     prot opt in     out     source               destination

标准方法是将它们设置为“setuid”,以便它们以根用户身份启动,然后在它们绑定到端口但开始接受到该端口的连接之前丢弃根用户特权。您可以在Apache和INN的源代码中看到这样的好例子。我听说莱特特警局是另一个很好的例子。

另一个例子是Postfix,它使用多个通过管道通信的守护进程,其中只有一两个守护进程(除了接受或发出字节外几乎不做任何事情)以根身份运行,其余的守护进程以较低的权限运行。

出于某种原因,没有人提到降低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之间进行选择。我们有这么多选择真是太好了。

使用systemd,您只需要稍微修改您的服务以接受预激活的套接字。

稍后可以使用systemd套接字激活。

不需要任何功能、iptables或其他技巧。

这是这个简单的python http服务器示例中的相关systemd文件的内容

文件httpd-true.service

[Unit]
Description=Httpd true 

[Service]
ExecStart=/usr/local/bin/httpd-true
User=subsonic

PrivateTmp=yes

文件httpd-true.socket

[Unit]
Description=HTTPD true

[Socket]
ListenStream=80

[Install]
WantedBy=default.target

在libcap网站上有一个文件共享库链接到非特权应用程序的实例。最近在回答一个关于向共享库添加功能的问题时提到了它。