只读挂载是从内核VFS层拦截write等系统调用的物理级防篡改机制,适用于/usr、/boot、/opt、Docker配置/证书目录等内容稳定且无需运行时变更的路径,需配合fstab配置、长语法挂载、tmpfs供给及chattr+i等协同防护。

只读挂载不是“不让写”的权限补丁,而是从内核 VFS 层直接拦截 write、truncate、unlink 等系统调用,让进程哪怕以 root 身份运行,也无法修改、覆盖或删除挂载点下的任何内容——这是物理级别的防篡改,不依赖用户态权限检查,也无法被 chmod 或 chown 绕过。
哪些路径适合只读挂载
核心判断标准是:内容稳定、无需运行时变更、被多个服务共享或强依赖。典型目标包括:
- /usr:二进制、库文件集中地,生产环境极少更新,挂为只读后可阻断对 /usr/bin/nginx 或 /usr/lib/systemd 的恶意替换
- /boot:内核镜像与 grub 配置所在,一旦被篡改将导致启动失败或加载后门
- /opt 或自定义部署目录:如 /var/www/html(静态资源)、/srv/app/conf(只读配置包),适用于镜像化分发或 CDN 回源场景
- Docker 容器内挂载的配置/证书目录:如 ./certs:/etc/tls:ro、./config:/app/config:ro,避免运行时被覆盖
不同场景下的只读挂载实操
机制要匹配使用阶段,不能混用:
-
主机系统分区:在 /etc/fstab 中添加 ro,noexec,nosuid,nodev,noatime,例如:
UUID=4eff9bdb /boot ext4 ro,noexec,nosuid,nodev,noatime 0 2
生效后执行 sudo mount -o remount /boot,再用 touch /boot/test 验证是否报错 Read-only file system -
Docker 容器:优先使用长语法,显式声明 read_only: true,例如:
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
或 docker run 中加 --read-only 并配合 --tmpfs 提供必要可写空间(如 /tmp、/run) - systemd 服务沙箱:用 ProtectSystem=strict 自动将 /usr、/boot、/etc 以只读 bind-mount 注入服务命名空间;搭配 ReadWriteDirectories= 显式放行 /var/lib/myapp 等真实需写路径,避免“全盘只读”导致崩溃
必须配套的关键措施
只读挂载单独使用容易失效或引发故障,需协同控制:
- 区分“挂载只读”和“路径只读”:挂载点设为 ro 后,其下所有子目录自动继承;但若某目录被 bind-mount 进来(如 /etc/myapp/conf),需单独对其挂载项设 ro,否则成为绕过缺口
- 禁止对根分区 / 直接设 ro:日志、锁文件、运行时状态均需写入,强行设置会导致服务无法启动;应聚焦子目录或独立分区
- 验证不能只看启动成功:进入容器或服务进程命名空间,执行 echo test > /path/to/file 和 rm /path/to/file,确认两者均返回 Read-only file system 错误
- 宿主机上敏感二进制可叠加 chattr +i:对通过 -v 挂载的授权工具等关键文件,在宿主机执行 chattr +i /host/path/tool.bin,即使容器有 root 权限也无法修改——这是内核级不可变属性,比挂载更底层
常见误区与避坑
很多“只读”配置看似生效,实则形同虚设:
- Windows 下仅勾选“只读属性”无效,必须通过 icacls 禁用写入类 NTFS 权限(如 modify、delete)
- ACL 设置中误给父目录 rwx,会导致“只读不删”策略完全失效——删文件靠的是目录 w 权限,不是文件自身权限
- fstab 中漏写 noexec,攻击者仍可能上传并执行恶意脚本;漏写 nosuid 则可能利用 setuid 程序提权
- 对 /etc 全局设 ro 前未评估服务依赖,导致 cron、dbus、systemd-networkd 等因无法写状态而静默退出

















