linux权限控制核心是能力边界管理,通过bounding(上限)、permitted(许可)、inheritable(可继承)三重机制实现最小权限;bounding set为硬性天花板,systemd-analyze capability查能力列表,setcap绑定文件能力,capsh或c api可运行时降权。

Linux 服务器权限控制的核心,不是“给不给 root”,而是“给哪几种能力、在什么范围生效”。Capability 边界设置,本质是用 Permitted(许可)、Inheritable(可继承) 和 Bounding(上限) 三重机制,把权限卡死在最小必要范围。关键不在堆权限,而在收边界。
明确能力边界:从 Bounding Set 开始收紧
Bounding Set 是所有能力的硬性天花板,一旦移除,进程及其全部子孙永远无法获得该能力——哪怕 setcap 设了、父进程有、甚至改 UID 也无效。这是最底层的安全锚点。
- 查看当前系统支持的能力列表:
systemd-analyze capability - 在 systemd service 文件中限制高危能力(如禁用 CAP_SYS_ADMIN):
CapabilityBoundingSet=~CAP_SYS_ADMIN CAP_SYS_MODULE CAP_SYS_PTRACE - 全局收紧(适用于安全加固场景):在内核启动参数中添加
systemd.capability_bounding_set=cap_net_bind_service cap_net_raw,只保留业务必需能力
按需授予文件能力:setcap 是起点,不是终点
能力必须绑定到可执行文件上才具备持久性,但仅设文件能力不等于进程自动启用——它只是为 Permitted 集提供来源之一。
- 允许普通用户绑定 80 端口:
sudo setcap cap_net_bind_service=+ep /usr/local/bin/myserver
(e表示 Effective 默认开启,p表示加入 Permitted) - 仅允许子进程继承 raw socket 权限,自身不启用:
sudo setcap cap_net_raw=i /usr/local/bin/packet-tool - 验证是否生效:
getcap /usr/local/bin/myserver,输出应含= cap_net_bind_service+ep
控制父子权限传递:Inheritable 是隔离关键
主进程常需高权(如监听端口、加载配置),但工作子进程只需极小权限。这时靠 Inheritable + 文件自身的 i 位配合,实现精准遗传。
- 主程序启动时带 cap_net_admin+i:
capsh --inh=cap_net_admin -- -c "./master" - 子进程执行的工具(如 ifconfig)本身也需设
cap_net_admin=i,否则 exec 后 Permitted 中不会出现该能力 - 检查运行中进程的实际能力:
cat /proc/<pid>/status | grep Cap</pid>,关注 CapInh(Inheritable)、CapPrm(Permitted)、CapEff(Effective)三行十六进制值
运行时动态降权:进程启动后还能收权限
很多服务只需在初始化阶段用某能力(如读取加密密钥),之后全程应清除。这靠运行时操作 Permitted 和 Effective 实现。
- 临时去掉能力再执行命令:
capsh --drop=cap_sys_time -- -c "date" - C 语言中放弃某能力(需先在 Permitted 中存在):
cap_t caps = cap_get_proc(); cap_clear_flag(caps, CAP_EFFECTIVE, CAP_NET_RAW); cap_set_proc(caps); - 推荐模式:启动时全量加载(e.g.,
cap_net_raw+eip),初始化完成后调用cap_clear_flag(..., CAP_EFFECTIVE, ...)关闭 Effective,只留 Permitted 备用











