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

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

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

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

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


当前回答

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

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

其他回答

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

好的,感谢那些指出系统和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中添加了这个功能。

出于某种原因,没有人提到降低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

将8080端口绑定为80端口,开放80端口:

sudo iptables -t nat -A OUTPUT -o lo -p tcp --dport 80 -j REDIRECT --to-port 8080
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT

然后以普通用户身份在8080端口上运行程序。

然后,您将能够在端口80上访问http://127.0.0.1