## 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 容器。你不希望里面的任何恶意脚本修改进程权限或者创建设备节点，你可以通过命令先移除**所有**默认能力，然后再按需授权该守护进程一个仅仅能绑端口的能力。

```bash
$ 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。

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

```bash
$ 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）**”的极端配置并不过分，这将使得即便程序本身漏洞百出，攻击面也被死死压缩在一个几乎毫无后续伸展潜力的受限维度中。
