在Docker中利用AppArmor限制容器对宿主机硬件访问,核心是创建自定义profile(如restricted-hw),在其中用deny /dev/sda rw, deny /dev/ttyUSB0 rw, deny /dev/nvme0n1 rw等语句显式拒绝目标设备读写,并通过--security-opt apparmor=restricted-hw加载生效。

在 Docker 中利用 AppArmor 限制容器对宿主机特定硬件(如 /dev/sda、/dev/ttyUSB0、/dev/nvme0n1 等)的读写,核心在于:**为容器加载自定义 AppArmor profile,并在 profile 中显式拒绝(deny)对目标设备节点的访问权限**。Docker 默认不启用 AppArmor(取决于宿主机系统),且默认 profile(如 docker-default)通常不限制大多数 /dev/ 设备——必须手动配置。
确认宿主机已启用 AppArmor 并支持 Docker
AppArmor 是 Linux 内核安全模块,仅在 Ubuntu、Debian、SUSE 等发行版中默认启用。运行以下命令验证:
-
检查内核是否启用 AppArmor:
cat /sys/module/apparmor/parameters/enabled→ 应输出Y -
确认 AppArmor 已加载策略:
aa-status→ 查看 loaded profiles 数量及状态 -
确认 Docker daemon 支持 AppArmor:
docker info | grep -i apparmor→ 应显示AppArmor: true - 若未启用,需在 GRUB 启动参数中添加
apparmor=1 security=apparmor,并重装apparmor-utils和apparmor-profiles包
编写专用 AppArmor profile 限制硬件设备访问
不能直接修改 docker-default,应创建新 profile(例如 restricted-hw),明确禁止对特定设备路径的读写。关键点:
- 设备节点路径(如
/dev/sdb)在容器内挂载后仍映射到宿主机设备文件,因此需在 profile 中按其**容器内可见路径**声明规则 - 使用
deny /dev/sdb rw,即可阻止读写;加l(lock)或k(kill)可增强防护,但rw已足够拦截常规 I/O - 避免使用通配符(如
/dev/sd*)除非必要,防止过度限制或漏放
示例 profile(保存为 /etc/apparmor.d/usr.sbin.restricted-hw):
#include <tunables/global>
<p>profile restricted-hw flags=(attach_disconnected,mediate_deleted) {</p><h1>include <abstractions/base></h1><h1>include <abstractions/docker-common></h1><h1>显式拒绝访问敏感块设备</h1><p>deny /dev/sda rw,
deny /dev/sdb rw,
deny /dev/nvme0n1 rw,
deny /dev/ttyUSB0 rw,</p><h1>可选:限制 /dev/shm、/dev/mqueue 等 IPC 设备</h1><p>deny /dev/shm/<strong> rwkl,
deny /dev/mqueue/</strong> rw,</p><h1>允许基础设备(必须保留,否则容器无法启动)</h1><p>/dev/pts/** rw,
/dev/console rw,
/dev/zero rw,
/dev/null rw,
/dev/random r,
/dev/urandom r,
}</p>加载 profile:sudo apparmor_parser -r /etc/apparmor.d/usr.sbin.restricted-hw
运行容器时指定 AppArmor profile
Docker 不会自动应用新 profile,必须通过 --security-opt 显式绑定。注意 profile 名称是文件名中去掉路径和扩展后的部分(即 usr.sbin.restricted-hw):
- 启动容器:
docker run --security-opt apparmor=restricted-hw -it ubuntu:22.04 - 验证是否生效:
docker exec <container_id> ls -l /dev/sdb可见文件存在,但执行dd if=/dev/zero of=/dev/sdb bs=1M count=1会报错Permission denied - 查看容器实际使用的 profile:
cat /proc/<pid>/attr/current(其中 pid 为容器 init 进程 PID),应显示restricted-hw (enforce)
注意事项与常见问题
AppArmor 对硬件设备的控制依赖于路径匹配和权限语义,以下情况需特别留意:
-
设备热插拔或动态挂载:若容器运行时新设备(如 USB 摄像头)出现在
/dev/,而 profile 未提前声明 deny,则可能被允许访问。建议结合 udev 规则 + AppArmor 静态限制 -
特权容器(--privileged)会绕过所有 AppArmor 策略:禁用该选项,改用
--device-read-only或--device精确挂载所需设备 -
容器内 mknod 创建设备节点无效:AppArmor 默认禁止容器内
mknod,无需额外限制;重点仍是防止挂载宿主机设备后非法访问 - SELinux 与 AppArmor 不兼容:同一系统不可同时启用两者,若 SELinux 启用,AppArmor 将被禁用


















