Pages

Thursday, 28 September 2023

如何允许非root进程绑定低位端口

 

众所周知,在Linux中,要想绑定端口号在1024以下的低位端口,是需要root权限的。但是,如果我又想绑定低位端口,又不想以root身份运行程序,该怎么办?答案是,setcap命令。

一、使用条件

1、您的Linux内核版本至少为2.6.24。

2、文件不能是脚本。也就是说你必须将CAP_NET_BIND_SERVICE功能应用到可执行文件本身,而不是脚本中指向的其他应用。如果赋予了该文件CAP_NET_BIND_SERVICE能力,其他应用滥用用这个文件就可能在安全性上造成隐患。

3、如果你的程序使用自己的.../lib/的共享库,而Linux将在任何具有像setcap或suid这样的特权提升的程序上禁用LD_LIBRARY_PATH,将导致不能使用。

二、实现方法

使用如下命令给这个程序附加CAP_NET_BIND_SERVICE权限即可。注意,这条命令需要以root身份执行:

sudo setcap CAP_NET_BIND_SERVICE=+eip /path/to/binary

三、实现原理

接下来,我就把上面这条命令一点点拆开,解释清楚它到底干了什么。

1、Capabilities

首先介绍一下capabilities。在Linux内核版本2.2开始,Linux将一系列的超级管理员权限细分成了一个个可以单独开启关闭的单元,以提供更细粒度的权限控制,这些单元,就被称之为capabilities。详细的capabilities列表可以参考Man Page Capabilities(7)

2、CAP_NET_BIND_SERVICE

CAP_NET_BIND_SERVICE是Linux系统中超级管理员权限的细分单元,拥有CAP_NET_BIND_SERVICE能力的程序,就可以绑定端口号在 1024以下的特权端口。

3、setcap

那么,该如何设置CAP_NET_BIND_SERVICE呢?答案就是setcap命令。上文所提到的命令,就是给指定的这个二进制程序增加CAP_NET_BIND_SERVICE权限。

在CAP_NET_BIND_SERVICE后面,用=+相连接的,则是开启CAP_NET_BIND_SERVICE的模式。模式有如下三种:

e:Effective,意为这个能力是启用的。

p:Permitted,意为这个能力是允许被使用的。

i:inherited,意为这个能力可以被其子进程继承。

在 setcap命令中,使用加号来开启这个模式,或者使用减号来关闭这个模式。

4、查询某个程序拥有的权限

getcap /path/to/binary
#例如查询ping命令拥有的权限
getcap /bin/ping
/bin/ping = cap_net_raw+ep

5、清除某个程序拥有的权限

setcap -r /path/to/binary

四、守护进程使用低位端口

当某个程序当做守护进程运行,需要使用1024以下的低位端口时,无须使用步骤二的方法实现。可以在service的配置文件中指定 capabilities:

[Service]
# 该服务仅可以使用哪些capabilities
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
# 以非root用户运行程序时需要设定此参数
AmbientCapabilities=CAP_NET_BIND_SERVICE

参考资料

  1. Man Page Capabilities(7)
  2. Man Page setcap(8)
  3. Man Page cap_from_text(3)
  4. getcap, setcap and file capabilities - insecure.ws
  5. Is there a way for non-root processes to bind to “privileged” ports on Linux? - Stack Overflow
  6. Linux 的 capabilities 机制


No comments:

Post a Comment