seccomp 是限制容器系统调用的首选机制,通过 BPF 过滤器白名单精准拦截 syscall;AppArmor 作为补充,基于路径和权限实现资源级控制,两者协同构成纵深防御。

在 Linux 中,限制容器的系统调用主要有两种互补机制:AppArmor 和 seccomp。它们作用层级不同——AppArmor 是基于路径和访问权限的强制访问控制(MAC)框架,侧重于文件、网络、能力等资源访问控制;seccomp(secure computing mode)则直接过滤系统调用(syscall),粒度更细、更底层。两者可同时使用,但目标不同:AppArmor 不擅长拦截特定 syscall(如 ptrace 或 mount),而 seccomp 无法限制文件路径访问或网络端口绑定。实际生产中,seccomp 是限制系统调用的首选且最有效手段,AppArmor 更适合作为补充策略加固整体运行环境。
用 seccomp 白名单限制容器系统调用
seccomp 通过 BPF 过滤器拦截不被允许的系统调用,默认行为是杀死进程。Docker 和 containerd 原生支持加载 seccomp profile(JSON 格式),推荐使用白名单模式("defaultAction": "SCMP_ACT_ERRNO"),只显式放行容器必需的 syscall。
- 获取基础 profile:Docker 自带默认 profile(
docker info | grep "Security Options"可查路径),也可用 官方示例 或docker run --rm -it --security-opt seccomp=unconfined alpine cat /proc/self/status | grep Seccomp验证是否启用 - 定制 profile:用 seccompiler(Rust 编写)或手动编写 JSON。例如禁止
reboot、kill(对非 init 进程无效,但可防误调)、setuid等高危调用:
{
"defaultAction": "SCMP_ACT_ERRNO",
"syscalls": [
{ "name": "read", "action": "SCMP_ACT_ALLOW" },
{ "name": "write", "action": "SCMP_ACT_ALLOW" },
{ "name": "openat", "action": "SCMP_ACT_ALLOW" },
{ "name": "mmap", "action": "SCMP_ACT_ALLOW" },
{ "name": "exit_group", "action": "SCMP_ACT_ALLOW" }
]
}- 运行时加载:保存为
minimal.json,启动容器时指定:docker run --security-opt seccomp=./minimal.json alpine sh -c 'reboot || echo "blocked" - 注意:某些 syscall(如
clone、execve)对容器运行时本身至关重要,不可盲目禁用;建议先用 audit-seccomp 工具捕获真实调用再裁剪
用 AppArmor 补充资源级限制(非 syscall 级)
AppArmor 不能直接“禁止某个系统调用”,但它能阻止触发该调用的上下文行为。例如:deny capability sys_admin, 会拒绝对应 capability,使相关 syscall(如 mount、umount)失败;deny /bin/bash px, 可防止执行 bash,间接避免大量 shell 相关 syscall。
- 编写 profile:定义容器进程的抽象规则(如
/usr/bin/containerd)或具体路径(如/opt/myapp/bin/server)。关键指令包括:
•capability:控制 capabilities(如net_raw、sys_chroot)
•file:读/写/执行/挂载权限(/etc/passwd r,、/tmp/** rwk,)
•network:协议与端口限制(network inet tcp,、network inet6 dgram,) - 加载 profile:
1. 保存为/etc/apparmor.d/usr.bin.myapp
2.sudo apparmor_parser -r /etc/apparmor.d/usr.bin.myapp
3. 启动容器时绑定 profile:
docker run --security-opt apparmor=myapp alpine ps aux - 验证生效:进入容器执行
cat /proc/1/attr/current应返回myapp (enforce);尝试违规操作(如mount -t tmpfs none /mnt)将报错Operation not permitted
组合使用与注意事项
seccomp + AppArmor 是纵深防御的有效实践,但需注意协同逻辑和兼容性:
- seccomp 在内核 syscall 入口处拦截,早于 AppArmor 的路径检查;若某 syscall 被 seccomp 拦截,AppArmor 规则不会触发
- Docker 默认启用 seccomp(使用内置 default.json),但 AppArmor profile 需手动启用且宿主机必须已加载 AppArmor 模块(
lsmod | grep apparmor)并启用(cat /sys/module/apparmor/parameters/enabled返回Y) - containerd 用户需在
/etc/containerd/config.toml中配置:[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]seccomp_profile = "/etc/containerd/seccomp.json"apparmor_profile = "myapp" - 调试技巧:容器启动失败时,检查
dmesg | tail -20查看 seccomp 拒绝日志(含 syscall number);用aa-status确认 profile 是否加载及处于 enforce 模式
替代方案与现实建议
对于多数场景,无需从零编写复杂 profile:
- 优先使用 Docker 官方维护的 default seccomp profile(已禁用约 44 个高危 syscall,如
keyctl、create_module、mbind) - 结合
--cap-drop=ALL --cap-add=NET_BIND_SERVICE精简 capabilities,比硬编码 syscall 更易维护 - 敏感服务(如数据库、API 网关)可进一步使用
docker run --read-only --tmpfs /run --tmpfs /tmp配合 seccomp,实现只读根文件系统 + 限定内存临时空间 - 如需动态 syscall 分析,可用
strace -f -e trace=network,process,file docker run ...快速识别必要调用











