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

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

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 $*

其他回答

在启动时:

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

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

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

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

现代Linux支持/sbin/sysctl -w net.ipv4.ip_unprivileged_port_start=0。

我尝试了iptables PREROUTING REDIRECT方法。在旧的内核中,IPv6似乎不支持这种类型的规则。但显然,现在ip6tables v1.4.18和Linux内核v3.8支持它。

我还发现PREROUTING REDIRECT对机器内启动的连接不起作用。要处理来自本地机器的连接,还需要添加一个OUTPUT规则-参见iptables端口重定向不适用于本地主机。例如:

iptables -t nat -I OUTPUT -o lo -p tcp --dport 80 -j REDIRECT --to-port 8080

I also found that PREROUTING REDIRECT also affects forwarded packets. That is, if the machine is also forwarding packets between interfaces (e.g. if it's acting as a Wi-Fi access point connected to an Ethernet network), then the iptables rule will also catch connected clients' connections to Internet destinations, and redirect them to the machine. That's not what I wanted—I only wanted to redirect connections that were directed to the machine itself. I found I can make it only affect packets addressed to the box, by adding -m addrtype --dst-type LOCAL. E.g. something like:

iptables -A PREROUTING -t nat -p tcp --dport 80 -m addrtype --dst-type LOCAL -j REDIRECT --to-port 8080

另一种可能是使用TCP端口转发。例如使用socat:

socat TCP4-LISTEN:www,reuseaddr,fork TCP4:localhost:8080

然而,这种方法的一个缺点是,在端口8080上侦听的应用程序不知道传入连接的源地址(例如用于日志记录或其他识别目的)。

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

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

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

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

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