Files
docker_practice/18_security/18.4_kernel_capability.md
2026-03-09 20:04:13 -07:00

3.9 KiB
Raw Blame History

18.4 内核能力机制

传统 Linux 的权限模型非常粗放:进程分为“特权进程”(以 root 用户 UID 0 运行)和“非特权进程”(其他 UID 运行)。这带来了一个致命问题——只要一个后台服务需要一个微小的特权(例如绑定低于 1024 的端口),就必须被赋予所有的 root 权限。一旦该服务被攻陷,系统便会全面沦陷。

为了解决这一问题Linux 引入了 能力机制Capabilities。它将传统的全能 root 权限划分为几十个细粒度的操作能力。

18.4.1 容器内置的 Capability 白名单

在默认情况下,即便一个容器是在以 root 用户运行Docker 也只为其内核授予了所有可用能力中的 一小部分“白名单”能力

常见的 Linux Capabilities 包含:

  • CAP_CHOWN: 修改文件所有者。
  • CAP_NET_BIND_SERVICE: 绑定特权端口(即 1024 以下的端口)。
  • CAP_NET_ADMIN: 网络管理的最高权限(例如调整路由配置,设置防火墙规则等)。
  • CAP_SYS_ADMIN: 被誉为“Linux 内核的特权网管”,允许各种高危操作(挂载磁盘、访问敏感设备等)。

为了在 “最小特权原则” 的指导下加强安全Docker 默认 移除了 大量可能导致容器大范围破坏宿主机的能力,例如:

  • 完全禁止了任何通过 CAP_SYS_ADMIN 进行的核心挂载或设备操作。
  • 禁止修改内核模块。
  • 禁止直接访问硬件套接字。

这种“非完整”的 root 用户能保证大部分应用在拥有其所需权限的同时,把恶意行为对系统的影响降到最低。

18.4.2 实战:添加与剥夺能力

当启动一个 Docker 容器时,我们可以利用 --cap-add(增加特权)和 --cap-drop(剥夺特权)两个参数精细地控制进程环境。

实战场景一:构建极限安全的 Web 靶机

假设你正在提供一个公共的 Web 容器。你不希望里面的任何恶意脚本修改进程权限或者创建设备节点,你可以通过命令先移除 所有 默认能力,然后再按需授权该守护进程一个仅仅能绑端口的能力。

$ docker run -d \
  --name max_secure_web \
  --cap-drop ALL \
  --cap-add NET_BIND_SERVICE \
  nginx:alpine

这里的 --cap-drop ALL 是实现“特权最小化”的最强杀手锏。此时,即便某黑客利用 0-Day 手段拿到了 Web 服务的容器 root Shell当他试图改变任何不属于他自己的进程配置或者所有权时系统都会报错拒绝访问。

实战场景二:需要捕获网络数据包的网络实验

假设容器内的主程序是一个网络嗅探器(如 tshark 或 tcpdump这显然不在 Docker 提供的默认白名单之内,因为该程序试图直接操纵底层网卡流量,会触发 Permission Denied。

此时,我们需要给它适当补发缺失的部分核心管理能力:

$ docker run -it --rm \
  --name network_sniffer \
  --cap-add NET_ADMIN \
  --cap-add NET_RAW \
  tshark-image /bin/bash

我们只授予了所需的网络管理控制NET_ADMIN和侦听底层套接字的权限NET_RAW而免去了赋予整个容器终极杀器 --privileged 参数。

Warning

大量开发人员遇到了“权限遭到拒绝”的错误时,往往习惯性图省事添加 --privileged 这个核选项。但这将把 宿主机上一切特权和所有访问设备完全投射给容器内的根用户,其危险性等价于根本没有做隔离!请务必查明进程出错的实际原因,精准施加必要的隔离 CAP_* 能力。

18.4.3 总结

利用能力机制Capabilities是进行精细化系统级访问控制的关键一环。遵循“白名单剥夺一切不必要权利(--cap-drop ALL”的极端配置并不过分,这将使得即便程序本身漏洞百出,攻击面也被死死压缩在一个几乎毫无后续伸展潜力的受限维度中。