
核心要点(TL;DR)
- 网页防篡改的核心是基线校验加实时监控,单靠备份无法及时发现篡改。
- inotifywait 监控站点目录,配合 SHA256 清单可在秒级定位被改文件。
- 自动恢复必须先隔离可疑文件再回滚,避免覆盖证据与二次感染。
- 监控进程需 systemd 托管并限制权限,否则重启即失效。
页面被植入黑链、首页被替换成跳转页,往往是客户或搜索引擎先发现,运维后知后觉。本文面向要动手的运维与站长,给出一套可落地的网页防篡改方案:用 inotify 实时监控 Nginx 站点目录,配合 SHA256 基线清单与可信备份实现自动恢复,所有步骤均可直接复制执行。
一、方案选型:为什么是「监控 + 基线 + 回滚」
单靠定期备份只能事后补救,单靠 WAF 只能拦截部分写入路径。网页防篡改的完整链路应包含三层:实时发现变更、判断变更是否可信、不可信则隔离并回滚。
| 方案 | 发现速度 | 能否自动恢复 | 适用场景 |
|---|---|---|---|
| 定时全量比对 | 分钟到小时级 | 可 | 兜底校验、低频目录 |
| inotify 实时监控 | 秒级 | 可 | 静态页面、模板、配置 |
| 只做备份 | 无 | 需人工 | 仅作恢复来源 |
结论:实时监控负责响应速度,定时校验负责兜底,备份目录提供可信恢复源,三者缺一不可。
二、准备基线:生成 SHA256 清单与可信备份
先确定受保护目录,例如 /data/www/site,排除上传、缓存与日志目录。生成基线清单:
cd /data/www/site find . -type f \ -not -path "./uploads/*" \ -not -path "./cache/*" \ -print0 | xargs -0 sha256sum > /opt/fim/baseline.sha256
同时做一份只读备份,供回滚使用:
mkdir -p /opt/fim/backup rsync -a --delete /data/www/site/ /opt/fim/backup/site/ chattr -R +i /opt/fim/backup/site
注意:基线清单本身也要保护,建议放在站点目录之外并设置只读权限,否则攻击者改文件同时改清单,校验就失去意义。
三、实时监控:inotifywait 监听关键事件
安装工具并确认内核参数足够:
apt install -y inotify-tools # 或 yum install -y inotify-tools sysctl fs.inotify.max_user_watches # 建议调大 sysctl -w fs.inotify.max_user_watches=524288
监控脚本核心逻辑是监听 modify、create、delete、move 事件,触发后调用校验与恢复函数:
#!/bin/bash
WATCH=/data/www/site
LOG=/var/log/fim/events.log
inotifywait -m -r -e modify,create,delete,move \
--exclude "./(uploads|cache)/" \
--format "%T %e %w%f" --timefmt "%F %T" "$WATCH" |
while read -r line; do
echo "$line" >> "$LOG"
/opt/fim/check_and_restore.sh "${line##* }"
done恢复函数要先隔离再回滚,保留证据:
#!/bin/bash
F=""
REL="${F#$WATCH/}"
ISO=/opt/fim/quarantine/$(date +%s)
mkdir -p "$ISO"
[ -f "$F" ] && mv "$F" "$ISO/"
rsync -a "/opt/fim/backup/site/$REL" "$F"
echo "$(date) restored $REL" >> /var/log/fim/restore.log四、兜底校验与告警收敛
用 cron 每小时跑一次全量比对,捕获监控进程漏掉的事件:
0 * * * * cd /data/www/site && sha256sum -c /opt/fim/baseline.sha256 --quiet >> /var/log/fim/verify.log 2>&1
告警要收敛,避免一次批量替换刷屏:按文件路径去重、5 分钟内同类事件合并为一条、恢复失败单独升级告警。监控进程用 systemd 托管,确保崩溃自动拉起:
[Unit] Description=FIM watcher [Service] ExecStart=/opt/fim/watch.sh Restart=always [Install] WantedBy=multi-user.target
在防护建议层面,可结合 AegisX 的网站文件完整性监控与告警能力,把本地脚本的事件统一接入平台做集中审计,减少多站点分散维护成本。
五、权限加固与上线检查清单
监控只是检测层,写入面收敛才是根治:Nginx 运行用户对静态目录只读,上传目录禁止执行脚本,配置目录仅 root 可写。
- 确认基线清单生成时间与当前文件一致,无测试残留。
- 确认排除目录覆盖上传、缓存、日志与临时文件。
- 用测试文件验证检测、告警、隔离、回滚四步全部生效。
- 重启服务器后确认监控服务自动启动且日志正常写入。
- 确认备份目录只读,且与站点目录不在同一块可写磁盘。
行动建议:先在预发环境跑通全链路,再按站点逐个灰度上线;把恢复日志纳入日常巡检,每周抽查一次隔离样本,确认没有误伤正常业务写入,网页防篡改才算真正落地。
常见问题(FAQ)
网页防篡改用 inotify 监控够用吗,还需要定时全量校验吗?
两者要配合使用。inotify 只能捕获监控进程运行期间的变更事件,进程重启、事件队列溢出或目录被替换时会漏报,因此必须叠加定时全量 SHA256 校验作为兜底。建议实时监控负责秒级响应,每小时或每天低峰期跑一次全量比对,两者结果统一走告警通道,才能覆盖删除、改名、批量替换等场景。
自动恢复会不会把攻击者留下的后门一起覆盖掉,导致证据丢失?
会,所以恢复流程不能直接覆盖。正确做法是先把被篡改文件移动到隔离目录并记录哈希、时间与进程信息,再从可信备份回滚,最后人工审计隔离样本。若站点存在上传目录或动态写入文件,应将其排除在自动恢复范围外,只对静态页面、模板和配置文件启用自动回滚,避免误伤业务数据。
监控脚本跑起来后 CPU 和磁盘 IO 会不会明显升高?
通常不会。inotify 是内核事件通知机制,空闲时几乎不占 CPU;开销主要来自恢复时的文件复制和定时全量校验的磁盘读取。建议对校验任务用 ionice 降低 IO 优先级,排除日志、缓存和上传目录,单站点目录控制在数万文件量级。若目录极大,可改为分片校验或只校验关键文件清单。
网站用了 CDN 或对象存储,本地文件监控还有意义吗?
有意义,但防护边界要分清。CDN 只缓存内容,源站文件被篡改后仍会回源分发;对象存储场景则要依赖版本控制与访问日志。本地监控负责源站静态文件与配置的完整性,CDN 侧应开启缓存刷新与内容校验,对象存储应启用版本管理与写权限收敛,三者组合才完整。
怎么验证防篡改配置真的生效,而不是只看到进程在跑?
做端到端演练:在监控目录新建测试文件并修改内容,观察日志是否记录事件、告警是否送达、文件是否在设定时间内恢复为基线版本;再删除文件验证重建逻辑,最后重启监控服务确认开机自启与状态正常。演练后清理测试文件并复核基线清单,避免把测试残留纳入校验范围。