45个进程永不杀——ServerGuard白名单机制与安全设计的工程取舍

4 阅读4分钟

自动运维最大的风险不是“不修”,而是“修坏了”。

你写了个脚本自动清理磁盘,结果删了正在写入的日志,程序崩了。你写了个脚本自动重启服务,结果nginx配置有错,重启一百次也没用,还把系统负载拉满了。你写了个脚本自动封IP,结果把自己的办公IP封了。

这种“越修越坏”的场景,才是自动运维真正的门槛。

ServerGuard的设计原则是:该出手时不犹豫,不该碰的不碰,不确定的交给你决定。 这篇文章拆解它的安全机制是怎么在代码层面落地的。

一、白名单机制:一个数组,一条死规矩 45+进程写死在白名单里,永远不杀:

Linux: systemd、sshd、nginx、httpd、apache2、mysqld、mariadbd、postgres、redis-server、mongod、php-fpm、php-cgi、bt-panel、pure-ftpd、vsftpd、named、postfix、dovecot、dockerd、containerd、cron、rsyslogd,以及ServerGuard自身。

Windows: System、smss.exe、csrss.exe、services.exe、lsass.exe、svchost.exe、w3svc、sqlservr.exe、mysqld.exe、postgres.exe、redis-server.exe、php-cgi.exe、nginx.exe,以及ServerGuard自身。

这个白名单不是配置文件里可以随便改的——它在代码层面强制生效。任何自动修复操作执行前,第一件事就是检查目标进程是否在白名单里。在,直接跳过。

二、11项安全检查链 每次自动修复执行前,必须通过11项检查:

  1. 目标进程是否在白名单 → 在则跳过
  2. 当前Kill次数是否超过预算(15次/小时)→ 超过则跳过
  3. 熔断器是否处于打开状态 → 是则跳过
  4. 系统CPU是否 > 95% → 是则进入存活模式,只告警
  5. 系统内存是否 > 95% → 是则降低操作优先级
  6. 目标是否是宝塔面板管理的进程 → 是则走特殊安全路径
  7. 操作类型是否触发级联防护 → 是则等待观察
  8. 是否处于维护窗口 → 是则跳过
  9. 是否处于开机保护期(开机5分钟内)→ 是则跳过
  10. 是否存在动作冲突(如磁盘满导致MySQL崩溃)→ 是则排序处理
  11. 全局紧急停止是否激活 → 是则全部跳过 任何一项不通过,操作不执行。 宁可不动,不做错事。

三、重启前配置预检 这是最容易被忽略但最关键的安全设计。

自动重启nginx之前,先跑nginx -t检查配置。配置有错就拒绝重启,服务保持原样至少还能跑。

同样的逻辑适用于:

Apache:apachectl configtest

SSH:sshd -t

预检不过,拒绝重启,并附上配置错误信息告警。

服务重启的优先级链:

reload(平滑重载,不断开现有连接)

restart(预检通过才执行)

启动后存活验证

四、重启风暴放弃机制 端口被占用时,重启100次也没用。

60秒内重启3次仍未恢复 → 判定重启无效 → 放弃30分钟 → 附自动诊断报告(systemctl日志尾部 + 端口被谁占用)。

不机械重试,不把系统拖垮。

五、级联防护 操作执行后,观察60秒。如果系统指标变差(CPU/内存/磁盘/网络任一恶化),停止后续操作。

Kill进程后,5分钟对比系统快照。系统更差则触发紧急停止。

核心思路:每次动手之后,先确认没搞坏,再决定要不要继续。

六、安全设计的取舍 为什么不用更“智能”的方案?

因为可解释性比智能更重要。自动运维场景下,每一步操作都必须能追溯到“为什么”。如果用了大模型来做决策,出了问题你根本无法复盘——“它觉得应该这样做”不是可接受的答案。

确定性规则 + 多层安全阀 = 可解释、可预测、可回滚。

七、总结 ServerGuard的安全设计本质上是把SRE的“信任但验证”原则工程化了:

信任:相信自动修复能解决问题

验证:11项检查链确保每次操作都是安全的

兜底:五层安全机制 + 一键急停

代码全部开源,白名单、检查链、熔断逻辑你都能在源码里找到。觉得哪个规则不对,直接改。

项目地址:

GitHub:suoten/ServerGuard

Gitee:suoten/ServerGuard