核心思路是切断不可信组件向磁盘写入能力,将其所有可写路径强制重定向至带限制的tmpfs内存区域:只读根文件系统+精准挂载noexec/nosuid/size限制的tmpfs到/tmp、/run、/var/log及组件专属路径,并配合能力降权与持续监控验证。

用 tmpfs 挂载防范不可信第三方组件写盘留痕,核心思路是:**切断其向磁盘落写的能力,把所有可写路径强制重定向到内存中,并确保这些内存区域不可执行、不可提权、有容量上限**。这不是单纯挂一个 /tmp 就完事,而是围绕组件行为建一道“只许进内存、不许碰磁盘”的隔离墙。
锁定根文件系统,从源头禁写
不可信组件常通过修改配置、注入脚本、生成日志等方式尝试在 /etc、/usr/bin、/var/log 等路径落盘。第一步必须启用只读根:
- 启动时加 --read-only,使整个
/变为只读(mount | grep "on / type"应显示ro) - 此时
apt install、echo > /etc/hosts、cp shell.sh /usr/local/bin全部失败 - 注意:仅这一步会让多数应用崩溃——必须配合后续 tmpfs 放行关键路径
精准挂载 tmpfs 到组件实际写入路径
不能只挂 /tmp;要根据组件真实行为,覆盖它可能写入的所有“合法出口”。常见路径包括:
-
/tmp:几乎所有程序默认临时目录 →
--tmpfs /tmp:rw,noexec,nosuid,size=20m -
/run 和 /var/run:存放 socket、PID、锁文件 →
--tmpfs /run:rw,noexec,nosuid,size=10m --tmpfs /var/run:rw,noexec,nosuid,size=10m -
/var/log:若组件坚持本地打日志(非 stdout)→
--tmpfs /var/log:rw,size=5m(不加 noexec,因日志文件无需执行) -
组件专属路径:如 Java 应用写
/app/logs或 Node.js 写/app/tmp→ 显式挂载--tmpfs /app/logs:rw,noexec,size=15m
关键点:每个 tmpfs 都设 size= 上限,避免组件疯狂写入耗尽宿主机内存。
堵死绕过路径与执行入口
攻击者可能尝试利用挂载点逃逸或执行恶意 payload,需叠加安全选项:
-
noexec:禁止在 tmpfs 路径下执行任何二进制或脚本(如
/tmp/malware.sh无法chmod +x && ./) - nosuid:忽略 setuid/setgid 位,防止利用 suid 二进制提权
- 避免使用
dev、proc、sysfs等危险挂载(除非绝对必要),防止组件通过 /proc/self/exe 或 /sys/module 提权 - 配合 --cap-drop=ALL --security-opt=no-new-privileges,进一步限制能力边界
验证与持续监控
挂载不是一劳永逸,需验证是否真正生效:
- 进入容器执行
find / -writable 2>/dev/null | grep -E "^/(tmp|run|var/run|app)",确认只有你挂载的路径可写 - 运行组件后,检查
df -h | grep tmpfs,确认各 tmpfs 占用合理,无异常增长 - 用
docker stats <容器名>监控内存总量,结合 tmpfs 使用量判断是否接近阈值 - 容器退出后,检查宿主机磁盘对应路径(如绑定卷或镜像层)是否确实无新增或修改文件
本质上,这是用内存换安全:所有痕迹只活在 RAM 里,容器停,痕迹清,磁盘上不留一丝证据。

















