服务依赖树加固核心是防攻击而非防崩溃,需切断非必要依赖、隔离关键路径、限制启动顺序攻击面,通过反向依赖分析、显式依赖审查、slice资源隔离、defaultdependencies=no精简、ipc通道封禁及failureaction=exit等手段实现。

系统服务依赖树加固不是为了“防止崩溃”,而是防止攻击者利用服务间的依赖关系,通过控制一个低权限服务,逐级提权或触发连锁故障,最终瘫痪关键服务(比如数据库因日志服务异常而拒绝写入、监控服务因网络配置服务失效而漏报)。核心思路是:**切断非必要依赖、隔离关键路径、限制启动顺序的攻击面**。
识别并精简服务依赖链
过度依赖会放大单点风险。先看清真实依赖关系,再裁剪:
- 用 systemctl list-dependencies --reverse servicename 查看哪些服务依赖目标服务(例如查
sshd被哪些服务反向依赖,可能暴露意外调用路径) - 用 systemctl show servicename | grep -E "Wants|Requires|After|Before" 提取显式依赖声明,对比实际运行时是否真需要这些关联
- 对非核心服务(如
avahi-daemon、bluetooth、cups),直接移除WantedBy=multi-user.target行,避免被默认拉起
拆分关键服务的启动上下文
让高价值服务不与基础服务共用同一启动环境,降低横向影响:
- 为数据库、Web服务等单独创建
.slice(如app.slice),在 unit 文件中添加 Slice=app.slice,配合systemd-run --scope -p MemoryLimit=2G限制资源边界 - 禁用隐式依赖:在 service 文件中显式设置 DefaultDependencies=no,然后手动补全真正需要的
After=network.target等最小集合 - 把日志收集(
journald)、审计(auditd)等支撑服务设为 Restart=on-failure 且 StartLimitIntervalSec=60,防止单次崩溃引发反复重启拖垮系统
限制服务间通信通道
依赖常通过套接字、D-Bus 或文件锁传递,封住非必要通路:
- 用 systemctl cat servicename | grep -A5 "Sockets=" 检查是否绑定了多余 socket;对不需要 IPC 的服务,删除
Sockets=行或设为 SocketMode=0600 - 在
/etc/systemd/system.conf中启用 RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6,禁止服务使用原始套接字或 netlink 等高危协议 - 对 D-Bus 服务,在
/usr/share/dbus-1/system.d/下对应 xml 文件中,用<deny own="xxx.xxx.xxx"></deny>明确拒绝无关接口注册
固化启动顺序与失败响应
防止攻击者通过伪造依赖或篡改 unit 文件扰乱启动逻辑:
- 用 systemd-analyze verify servicename.service 检查 unit 文件语法及依赖循环;对存在
Conflicts=或BindsTo=的服务,确认其语义是否真有必要 - 为关键服务设置 StartupCPUShares=512 和 StartupMemoryLimit=1G,确保启动阶段资源优先保障,避免被其他服务抢占导致超时失败
- 在 service 文件中配置 FailureAction=exit(而非默认的 ignore),使依赖它的服务在上游失败时立即终止,而不是盲目等待或降级运行











