seccomp核心是进程启动早期在main开头加载bpf过滤规则,纯内核态拦截非必需syscall,需用libseccomp设白名单、禁用ptrace/mount/execve等高危调用,且必须在fork/pthread_create前完成。

直接用 seccomp 限制关键进程的系统调用,核心是让进程在启动早期主动加载过滤规则,把非必需的 syscall 拦在内核入口。它不依赖容器或外部工具,纯内核机制,开销低、生效快,特别适合守护进程、网络服务、解析类程序等高风险暴露面。
必须在 main 开头安装,且不能有线程干扰
seccomp 规则必须在进程执行任何 fork()、pthread_create() 或第三方库初始化前完成加载。一旦子线程创建或动态库触发隐式系统调用(比如 glibc 初始化 mmap、brk),再装策略可能失败或漏放行。
- 确保 第一行有效代码就是 seccomp_init(),不要放在日志初始化、配置加载之后
- C++ 程序避免在全局对象构造函数里调用 seccomp;Go/Node.js 不适用此方式,它们需靠容器层 seccomp
- 验证是否生效:运行后执行
cat /proc/<pid>/status | grep Seccomp</pid>,输出为 2 表示已启用 filter 模式
用 libseccomp 写白名单,别碰 defaultAction 小写陷阱
手动写 BPF 字节码太重,推荐使用 libseccomp 封装。它把系统调用名自动转为编号,支持参数级过滤,还能导出 BPF 汇编用于审计。
- 安装开发包:
sudo apt install libseccomp-dev(Debian)或sudo dnf install libseccomp-devel(RHEL) - 链接时加
-lseccomp;头文件含<seccomp.h></seccomp.h> - 字段名严格区分大小写:
default_action(不是 defaultAction)、syscalls(不是 syscall)、architectures(不是 arch) - 基础允许集至少包含:
read、write、exit、exit_group、brk、mmap、munmap、rt_sigreturn、openat、close、fstat、statx
禁止高危调用要精准,不能一刀切删 openat
很多教程盲目禁用 openat、statx,结果程序连 /proc/self/exe 都读不了,Go panic、Python 导入失败、C++ std::filesystem 报错。真正该重点拦截的是逃逸和提权链关键环节:
-
必须禁用:
ptrace(调试劫持内存)、mount/umount2(突破根目录隔离)、chroot/pivot_root(绕过路径限制)、capset(篡改能力位)、execve/execveat(执行任意二进制) -
谨慎评估:
clone(Go runtime 和多线程程序强依赖)、epoll_wait(Node.js/Netty 必需)、socket(如仅需本地通信可限制 domain=AF_UNIX) - 用
strace -f -e trace=raw_syscall -p $(pidof your-process)抓真实调用,比凭经验猜更可靠
容器中用 JSON profile,路径和权限必须由 daemon 控制
Docker 或 containerd 加载 seccomp 是由后台 daemon 进程完成的,它以 root 身份运行,但**不继承你的 shell 当前路径或环境变量**。
- profile 文件必须是绝对路径,例如
/etc/docker/seccomp-restrict.json,不能用./profile.json或~/profile.json - 确认 daemon 可读:
sudo chmod 644 /etc/docker/seccomp-restrict.json,并检查 SELinux/AppArmor 是否阻断访问 - 启动命令示例:
docker run --security-opt seccomp=/etc/docker/seccomp-restrict.json nginx:alpine - 校验 JSON 语法:
jq -n -f /etc/docker/seccomp-restrict.json >/dev/null || echo "invalid"











