如何让非特权进程监听特权端口(上)

特权端口(也就是 1024 以下的低端口)是 Unix 系统里最似是而非的安全设计,没有之一。有时候我们希望一个服务程序能够监听在 80 之类的知名低端口(便利),但程序的整个生命周期又要避开 root 身份(安全)。这种对便利和安全的双重追求就让我们感到特权端口的设计是多么蛋疼了。

要解决这个问题,也有一些似是而非的通用办法。比如前置的应用层协议代理(例如 HTTP 反向代理),用户态端口转发(例如 rinetd/xinetd),或者本机防火墙做内核态转发。但这些方法还是有一定限制的,有时候并不合适。我们需要的是让非特权进程真正监听在低端口上。顺便说一下,有些人提到的 authbind/privbind 程序,虽然能解决问题,但用到了 suid 的 helper 程序……

幸好一些主要的 Unix 类操作系统发展到当代还是有办法解决这个问题的。

FreeBSD 可以用下面的指令关闭特权端口:

# sysctl net.inet.ip.portrange.reservedlow=0 net.inet.ip.portrange.reservedhigh=0

这样非特权进程就能直接监听低端口了。如果需要做权限控制,比如以 uid=80 启动的用户只能听80 端口,那么还需要启动 mac_portacl 模块。具体见 [PORTACL]_ 。

Solaris 可以通过:

# /usr/sbin/usermod -K defaultpriv=basic,net_privaddr <user_name>

给特定的用户赋予监听特权端口的权限。但是,没有类似 FreeBSD 的全局选项,而且也没有端口权限控制(如有,请指正)。

NetBSD、 OpenBSD、 Dragonfly BSD 似乎没有相应的机制, OS/X 不知,还有待探索。

Linux 情况比较混乱,且待下回分解。