systemd服务可通过组合ProtectSystem=strict、ProtectHome=read-only、PrivateTmp=yes等沙箱选项及ReadOnlyDirectories+ReadWriteDirectories实现精细化安全隔离,辅以RestrictAddressFamilies、NoNewPrivileges和CapabilityBoundingSet限制运行时环境,需逐步调试避免兼容性问题。

systemd 服务可以通过 沙箱化(Sandboxing) 和 文件系统只读(Read-OnlyFileSystem) 配置显著提升安全性,限制服务对系统资源的访问范围,防止横向渗透或意外写入。关键在于合理组合使用 systemd 提供的隔离选项,而非简单开启所有开关。
基础沙箱化:启用默认保护机制
systemd 提供了多个开箱即用的沙箱选项,建议在服务单元文件中至少启用以下几项:
-
ProtectSystem=strict:将
/usr、/boot、/etc挂载为只读,阻止修改核心系统路径 -
ProtectHome=read-only:隐藏用户主目录(
/home、/root、/run/user),或设为只读,防敏感数据泄露 -
ProtectKernelTunables=yes:禁止通过
/proc/sys、/sys修改内核参数 - ProtectKernelModules=yes:阻止加载/卸载内核模块
-
PrivateTmp=yes:为服务提供独立的
/tmp和/var/tmp,避免临时文件冲突或窥探
文件系统只读:按需放开写入点
启用 ReadOnlyDirectories 或全局 ReadWriteDirectories 比单纯设 ReadOnlyFileSystem=yes 更灵活。后者会将整个根文件系统设为只读,几乎必然导致服务失败。
- 用 ReadOnlyDirectories=/ 实现“默认只读”,再显式声明可写路径:
ReadWriteDirectories=/var/lib/myservice<br>ReadWriteDirectories=/run/myservice
- 若服务需日志写入,保留
/var/log/myservice可写,但避免开放/var/log全局可写 - 慎用
ReadWritePaths=—— 它不检查父目录权限,可能绕过只读限制;优先用ReadWriteDirectories
网络与进程隔离:减少攻击面
沙箱不仅是文件系统控制,还需限制运行时环境:
-
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6:禁用不必要的协议族(如
AF_NETLINK、AF_PACKET),防本地提权或抓包 - RestrictNamespaces=yes:禁止创建新命名空间(user/net/pid 等),防止逃逸
-
NoNewPrivileges=yes:确保进程无法通过
execve获得额外权限(如 setuid 二进制) -
CapabilityBoundingSet= 配合 DropCapability=:显式限定所需能力,例如仅保留
CAP_NET_BIND_SERVICE绑定低端口,移除CAP_SYS_ADMIN等高危能力
调试与兼容性注意点
激进沙箱可能导致服务启动失败,排查时可逐步放开限制:
- 先启用
PrivateTmp+ProtectSystem=strict,观察是否因写/tmp或读/etc失败 - 用
journalctl -u myservice -o cat查看错误;配合strace(在ExecStartPre中调用)定位被拒的系统调用 - 某些程序硬编码依赖
/dev/shm或/proc/self/fd,需用BindPaths=显式挂载或改用RuntimeDirectoryMode=控制权限 - 容器化服务(如 Podman)通常已自带更强隔离,systemd 沙箱可适度简化,重点保
NoNewPrivileges和ProtectKernel*
不复杂但容易忽略:沙箱效果取决于所有相关选项协同生效,单开一两项作用有限。从最小可行集开始,结合服务实际行为逐步加固,比套用模板更可靠。










