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

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

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

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

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


当前回答

还有一种“djb方式”。您可以使用此方法以运行在tcpserver下任何端口上的根用户身份启动您的进程,然后在进程启动后,它将把进程的控制权立即交给您指定的用户。

#!/bin/sh

UID=$(id -u username)
GID=$(id -g username)
exec tcpserver -u "${UID}" -g "${GID}" -RHl0 0 port /path/to/binary &

更多信息,请参见:http://thedjbway.b0llix.net/daemontools/uidgid.html

其他回答

另外两种简单的可能性:Daemon和Proxy

守护进程

对于“一个绑定在低端口上的守护进程并将控制权交给您的守护进程”,有一个旧的(不流行的)解决方案。它被称为inetd(或xinetd)。

缺点是:

你的守护进程需要在stdin/stdout上对话(如果你不控制守护进程——如果你没有源代码——那么这可能是一个showstopper,尽管一些服务可能有inetd兼容性标志) 每个连接都会生成一个新的守护进程 这是链条上的一环

优点:

可以在任何旧的UNIX上使用 一旦系统管理员设置了配置,就可以开始开发了(当重新构建守护进程时,可能会失去setcap功能吗?然后你就得回到你的管理员那里,“请,先生……”) Daemon不需要担心网络的问题,只需要在stdin/stdout上进行对话 是否可以按照请求配置为以非根用户执行守护进程

代理

另一种替代方案:从特权端口到任意高编号端口(您可以在其中运行目标守护进程)的经过修改的代理(netcat或更健壮的代理)。(Netcat显然不是一个生产解决方案,但“只是我的开发盒”,对吧?)通过这种方式,您可以继续使用服务器的网络支持版本,只需要root/sudo启动代理(在引导时),而不依赖复杂/潜在的脆弱功能。

将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

使用privbind实用程序:它允许非特权应用程序绑定到预留端口。

使用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

我尝试了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上侦听的应用程序不知道传入连接的源地址(例如用于日志记录或其他识别目的)。