文章目录
-
- [一. `--privileged` 获取到了哪些权限?](#一.
--privileged获取到了哪些权限?) -
- [1.1. 解锁所有 Linux Capabilities(能力)](#1.1. 解锁所有 Linux Capabilities(能力))
- [1.2. 访问所有设备(Devices)](#1.2. 访问所有设备(Devices))
- [1.3. 解除 AppArmor/SELinux 限制(部分情况)](#1.3. 解除 AppArmor/SELinux 限制(部分情况))
- [二. 特权模式使用场景](#二. 特权模式使用场景)
-
- [2.1. **运行 Docker-in-Docker (DinD)**:](#2.1. 运行 Docker-in-Docker (DinD):)
- [2.2. **系统级监控代理**:](#2.2. 系统级监控代理:)
- [2.3. **硬件直通与驱动开发**:](#2.3. 硬件直通与驱动开发:)
- [2.4. **网络调试工具**:](#2.4. 网络调试工具:)
- [2.5. **虚拟化嵌套**:](#2.5. 虚拟化嵌套:)
- [三. 安全风险(非常重要!)](#三. 安全风险(非常重要!))
-
- [3.1. **逃逸到宿主机**:](#3.1. 逃逸到宿主机:)
- [3.2. **破坏宿主机内核**:](#3.2. 破坏宿主机内核:)
- [3.3. **窃取数据**:](#3.3. 窃取数据:)
- [四. 最佳实践:最小权限原则(Least Privilege)](#四. 最佳实践:最小权限原则(Least Privilege))
-
- [4.1. 错误做法(过度授权)](#4.1. 错误做法(过度授权))
- [4.2. 正确做法(按需授权)](#4.2. 正确做法(按需授权))
-
- [4.2.1. 只需要抓包网络流量](#4.2.1. 只需要抓包网络流量)
- [4.2.2. 只需要访问某个 USB 设备](#4.2.2. 只需要访问某个 USB 设备)
- [4.2.3. 需要加载内核模块](#4.2.3. 需要加载内核模块)
- [五. 如何检查容器是否处于特权模式?](#五. 如何检查容器是否处于特权模式?)
- [六. 总结对比](#六. 总结对比)
- [七. 建议](#七. 建议)
- [八. 参考文档](#八. 参考文档)
- [一. `--privileged` 获取到了哪些权限?](#一.
Docker 的 --privileged 参数是一个重要的配置选项,它允许 容器绕过额外的安全限制,提供类似于运行在宿主机上的普通进程的权限 。默认情况下,Docker 容器运行在隔离的环境中,其能力(capabilities)被限制,以防止它们访问宿主机的某些敏感资源或执行潜在危险的操作。使用 --privileged 参数可以提升容器的权限,使其能够执行一些通常不允许的操作,它几乎获得了 宿主机 root 用户的所有能力 ,并且可以访问宿主机上的 所有设备 。
一. --privileged 获取到了哪些权限?
正常运行的 Docker 容器是受到严格隔离和限制的(通过 Namespace 和 Cgroups)。而 --privileged 模式主要解除了以下两层限制:
1.1. 解锁所有 Linux Capabilities(能力)
Linux 内核将 root 权限细分为几十种具体的"能力"(如 NET_ADMIN, SYS_MODULE, SYS_PTRACE 等)。
- 普通容器默认只保留极少数的安全能力。
- 特权容器拥有全部 ~30+ 种能力。
- 例如:它可以修改网络配置、加载内核模块、追踪其他进程、修改系统时间等。
1.2. 访问所有设备(Devices)
- 普通容器 只能访问显式映射的设备(如
-v /dev/sda:/dev/sda)。 - 特权容器 可以访问宿主机
/dev下的所有设备文件 。- 这意味着它可以读写硬盘、操作 USB 设备、访问 GPU、甚至直接操作内存设备。
1.3. 解除 AppArmor/SELinux 限制(部分情况)
- 在某些配置下,特权模式可能会禁用或放宽宿主机的安全模块(如 AppArmor 或 SELinux)对容器的限制。
二. 特权模式使用场景
2.1. 运行 Docker-in-Docker (DinD):
- 在 CI/CD pipeline 中,你需要在一个容器里再启动 Docker 守护进程来构建镜像。这需要挂载 cgroupfs 和操作设备,必须用特权模式。
2.2. 系统级监控代理:
- 如 Datadog Agent、Prometheus Node Exporter 等,需要读取宿主机的内核指标、网络栈信息、磁盘 IO 等底层数据。
2.3. 硬件直通与驱动开发:
- 需要直接操作 USB 设备、串口、GPIO、GPU 进行底层开发或测试。
2.4. 网络调试工具:
- 如
tcpdump、wireshark在容器内抓包,需要NET_RAW和NET_ADMIN能力(虽然可以用--cap-add替代,但特权模式更简单粗暴)。
2.5. 虚拟化嵌套:
- 在容器内运行 KVM/QEMU虚拟机。
三. 安全风险(非常重要!)
--privileged 是 Docker 中最大的安全漏洞之一。
如果攻击者突破了特权容器内的应用,他们几乎可以完全控制宿主机:
3.1. 逃逸到宿主机:
- 攻击者可以通过挂载宿主机的根文件系统 (
mount /dev/sda1 /mnt) 直接修改宿主机的文件。 - 可以修改
/etc/shadow获取宿主机 root 密码。 - 可以安装 rootkit 或后门程序。
3.2. 破坏宿主机内核:
- 可以加载恶意内核模块导致宿主机崩溃(Kernel Panic)。
3.3. 窃取数据:
- 可以读取宿主机上其他容器的数据,甚至宿主机的敏感文件。
原则 :永远不要在生产环境中对不受信任的代码或公共镜像使用
--privileged。
四. 最佳实践:最小权限原则(Least Privilege)
不要直接使用 --privileged,而是使用 --cap-add 和 --device 按需授权。
4.1. 错误做法(过度授权)
bash
docker run --privileged my_monitoring_app
4.2. 正确做法(按需授权)
4.2.1. 只需要抓包网络流量
bash
# 只赋予网络管理能力,而不是全部权限
docker run --cap-add NET_ADMIN --cap-add NET_RAW my_sniffer_app
4.2.2. 只需要访问某个 USB 设备
bash
# 只映射特定的设备文件,并赋予相应权限
docker run --device /dev/ttyUSB0:/dev/ttyUSB0 my_serial_app
4.2.3. 需要加载内核模块
bash
# 只赋予系统模块管理能力
docker run --cap-add SYS_MODULE my_driver_test
你可以通过 man 7 capabilities 查看 Linux 所有可用的能力列表,并根据应用需求逐个添加。
五. 如何检查容器是否处于特权模式?
bash
# 查看容器详细信息
docker inspect <container_id> | grep -i privileged
# 输出示例:
# "Privileged": true,
或者在容器内部检查:
bash
# 进入容器
docker exec -it <container_id> sh
# 查看当前进程的能力
cat /proc/1/status | grep Cap
# 如果 CapEff 全是 ffffffffff,说明是特权模式
六. 总结对比
| 特性 | 普通容器 | 特权容器 (--privileged) |
|---|---|---|
| Linux Capabilities | 仅保留少量安全能力 | 拥有全部能力 |
| 设备访问 | 仅限显式映射的设备 | 访问宿主机所有设备 |
| 文件系统隔离 | 强隔离 | 可挂载宿主机文件系统 |
| 安全性 | 高(相对) | 极低(等同于宿主机 Root) |
| 适用场景 | 大多数应用服务 | DinD、底层监控、硬件调试 |
七. 建议
- 能不用就不用 :90% 的场景可以通过
--cap-add和--device解决。 - 如果必须用 :
- 确保镜像来源可信。
- 不要将特权容器暴露在公网。
- 定期审计特权容器的使用情况。
- 考虑使用 Kata Containers 或 gVisor 等沙箱技术提供更强的隔离(即使特权模式也无法轻易逃逸)。
八. 参考文档
1、https://cloud.tencent.com/developer/article/2285255
2、https://www.docker.com/blog/docker-can-now-run-within-docker/
3、https://xz.aliyun.com/news/12944
4、https://blog.csdn.net/yuelai_217/article/details/161049492