Agent调用Shell命令沙箱隔离
Agent调用Shell命令时如果直接交给宿主机执行,一旦命令被注入或业务逻辑异常,可能直接破坏系统环境。
更稳妥的做法是把命令放入独立沙箱,比如Docker容器或Firejail进程沙箱,让危险操作被限制在一个可丢弃的隔离层里。
本文会给出两种可落地的隔离方案,并说明配置方法、验证步骤和容易踩的坑。
先想清楚:沙箱到底隔离了什么
沙箱隔离不是简单换个用户运行命令,而是要控制四个维度:
- 文件系统:命令能否读写宿主机目录,能否看到敏感文件。
- 网络:命令能否访问内网、外网或监听端口。
- 系统调用:命令能否执行 mount、reboot、加载内核模块等敏感操作。
- 资源限制:命令长时间占用 CPU、内存时会不会拖垮宿主机。
理解了这四点,再看下面的方案就很容易明白每条参数的作用。
方案一:用Docker容器做一次性命令沙箱
这是最常见的做法,适合 Agent 执行短生命周期命令。
先确认 Docker 已安装:
which docker && docker --version
运行命令时使用 --rm 让容器退出后自动删除,同时切断网络和降权:
docker run --rm --network none --cap-drop ALL -v /tmp/agent-work:/work -w /work alpine sh -c "echo hello && id"
参数解释:
--network none:容器内没有网络接口,无法外联。--cap-drop ALL:丢弃所有内核能力,禁止挂载、改主机名等特权操作。-v /tmp/agent-work:/work:只挂载一个临时工作目录,宿主机其他路径不可见。
如果需要输出结果供 Agent 读取,把输出重定向到挂载目录里的文件:
docker run --rm --network none -v /tmp/agent-work:/work alpine sh -c "pwd > /work/result.txt"
宿主机的 /tmp/agent-work/result.txt 就能拿到结果。
方案二:用Firejail做进程级沙箱
如果 Agent 直接运行在宿主机上,不方便每次都用 Docker 封装,可以用 Firejail 给命令加一层进程沙箱。
安装:
apt install firejail # Debian/Ubuntu
执行命令时加入隔离参数:
firejail --net=none --private --nogroups sh -c "whoami && pwd"
参数含义:
--net=none:禁止网络访问。--private:给进程一个临时 HOME 目录,读写内容不会落到真实用户目录。--nogroups:取消附加用户组,降低权限提升风险。
Firejail 还能限制文件系统边界,例如只允许访问 /tmp/agent-work:
firejail --net=none --private=/tmp/agent-work sh -c "ls /"
此时命令只能看到 /tmp/agent-work 下的内容,宿主机根目录不可见。
必须避开的几个坑
容器不等于完全隔离内核漏洞。
Docker 共享宿主机内核,遇到容器逃逸漏洞仍有风险。
生产环境建议配合 seccomp 配置文件限制系统调用,或者使用 gVisor 这类更严格的安全运行时。
不要挂载宿主机根目录。
有人图省事写 -v /:/host,等于把整个宿主机文件系统送进容器,一旦命令是 rm -rf,后果无法挽回。
只挂载必要的读写目录即可。
务必加超时机制。
沙箱内命令可能因为等待输入或网络原因卡死,Agent 侧需要设置超时,比如用 timeout 30 docker run ...,避免容器长时间占用资源。
输出文件注意属主权限。
容器内用户是 root,写出的文件在宿主机上也是 root 属主,如果 Agent 进程是普通用户,可能读不了。
可以用 -u $(id -u):$(id -g) 指定容器内用户,或者手动修改目录属主。
怎么验证隔离真的生效
执行完命令后,从三个角度检查:
- 网络是否断开:在容器或 Firejail 内执行
ping 114.114.114.114,如果超时或无权限,说明网络被正确隔离。 - 文件系统是否受限:运行
ls /,Docker 容器内看到的是完整镜像目录,默认不可见宿主机路径;Firejail 的--private模式下只能看到临时目录。 - 进程是否残留:
docker ps -a应该没有之前运行过的容器;firejail --list查看当前沙箱进程,结束后应为空列表。
最后再检查宿主机上的 /tmp/agent-work 是否只有预期的输出文件,确认没有多余写入。
Agent 调用 Shell 命令的沙箱隔离,核心思路就是让命令在受限环境里“用完即弃”。
先跑通 Docker 或 Firejail,再根据实际业务调整挂载目录和网络策略,就能把宿主机被误操作的风险降到最低。
如果你遇到命令执行后权限不足或网络不通,回头检查上面提到的参数即可。