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

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

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

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

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


当前回答

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

其他回答

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

Systemd是一个sysvinit的替代品,它有一个选项来启动具有特定功能的守护进程。Options Capabilities=, CapabilityBoundingSet= in system .exec(5) manpage。

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

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

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

socat tcp6-listen:80,fork tcp6:8080

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

我知道这是一个老问题,但是现在有了最新的(>= 4.3)内核,这个问题终于有了一个很好的答案——环境能力。

快速的答案是从git中获取libcap的最新(尚未发布的)版本的副本并编译它。将生成的progs/capsh二进制文件复制到某个地方(/usr/local/bin是一个不错的选择)。然后,作为根用户,使用

/usr/local/bin/capsh --keep=1 --user='your-service-user-name' \
    --inh='cap_net_bind_service' --addamb='cap_net_bind_service' \ 
    -- -c 'your-program'

按顺序,我们是

声明当切换用户时,我们希望保持当前的功能集 切换用户和组到“your-service-user-name” 将cap_net_bind_service功能添加到继承的&环境集 派生bash -c 'your-command'(因为capsh会自动用——后面的参数启动bash)

这里隐藏着很多秘密。

Firstly, we are running as root, so by default, we get a full set of capabilities. Included in this is the ability to switch uid & gid with the setuid and setgid syscalls. However, ordinarily when a program does this, it loses its set of capabilities - this is so that the old way of dropping root with setuid still works. The --keep=1 flag tells capsh to issue the prctl(PR_SET_KEEPCAPS) syscall, which disables the dropping of capabilities when changing user. The actual changing of users by capsh happens with the --user flag, which runs setuid and setgid.

The next problem we need to solve is how to set capabilities in a way that carries on after we exec our children. The capabilities system has always had an 'inherited' set of capabilities, which is " a set of capabilities preserved across an execve(2)" [capabilities(7)]. Whilst this sounds like it solves our problem (just set the cap_net_bind_service capability to inherited, right?), this actually only applies for privileged processes - and our process is not privileged anymore, because we already changed user (with the --user flag).

新的环境能力集解决了这个问题——它是“在一个没有特权的程序的执行中保存的一组能力。”通过将cap_net_bind_service放在环境集中,当capsh exec执行我们的服务器程序时,我们的程序将继承此功能,并能够将侦听器绑定到低端口。

如果您有兴趣了解更多信息,功能手册页详细解释了这一点。通过strace运行capsh也是非常有用的!