网页防篡改实操:inotify+rsync 实现变更告警与恢复 核心要点图解,inotifywait 监听站点目录事件,配合 rsync 从可信源回滚,可把篡改恢复时间压到秒级。;监控要排除缓存、日志、上传目录,否则误报会淹没真实告警。;恢复必须从只读备份源拉取,禁止在受害机上原地备份,避免污染。;用 systemd 托管监控脚本并加日志轮转,才能长期稳定运行。
网页防篡改实操:inotify+rsync 实现变更告警与恢复 · 核心要点一图读懂(AegisX)

核心要点(TL;DR)

  • inotifywait 监听站点目录事件,配合 rsync 从可信源回滚,可把篡改恢复时间压到秒级。
  • 监控要排除缓存、日志、上传目录,否则误报会淹没真实告警。
  • 恢复必须从只读备份源拉取,禁止在受害机上原地备份,避免污染。
  • 用 systemd 托管监控脚本并加日志轮转,才能长期稳定运行。

网站被挂马、首页被替换,最怕的不是被改,而是几个小时甚至几天后才发现。搜索引擎收录异常、用户投诉、品牌受损,往往都发生在你还没察觉的窗口期。本文给出一套可直接落地的网页防篡改方案:用 inotifywait 监听站点目录,发现变更立即告警,并用 rsync 从可信备份源自动回滚,把恢复时间从小时级压到秒级。

一、方案原理:监听、判断、恢复三步走

inotify 是 Linux 内核提供的文件系统事件通知机制,inotifywait 是其命令行工具。它能在文件被写入、移动、删除的瞬间触发回调,无需轮询扫描,开销低、延迟小。配合 rsync 的增量同步能力,就形成闭环:

  • 监听:inotifywait 递归监控站点根目录,捕获 modify、create、move、delete 事件。
  • 判断:过滤白名单目录与临时文件,命中可疑变更则记录并告警。
  • 恢复:调用 rsync 从只读备份源拉取对应文件,覆盖被篡改内容,并保留现场副本。
关键前提:备份源必须是独立、只读、可信的,不能放在被监控的同一台机器同一目录,否则攻击者改一处,备份一起被污染。

二、环境准备与依赖安装

以 CentOS/RHEL 与 Debian/Ubuntu 为例,安装监控与同步工具:

# CentOS / RHEL
yum install -y inotify-tools rsync

# Debian / Ubuntu
apt update && apt install -y inotify-tools rsync

确认内核参数足够,避免大目录监控报错:

cat /proc/sys/fs/inotify/max_user_watches
# 建议调大
sysctl -w fs.inotify.max_user_watches=524288
echo 'fs.inotify.max_user_watches=524288' >> /etc/sysctl.conf

规划目录:站点目录 /var/www/html,可信备份源 /data/www_baseline(建议挂载为只读),隔离区 /data/quarantine 用于留存被改文件。

三、编写监控与自动恢复脚本

核心脚本 /usr/local/bin/web_guard.sh,逻辑是逐行读取 inotifywait 输出,命中规则后告警并回滚:

#!/bin/bash
SITE=/var/www/html
BASE=/data/www_baseline
QUAR=/data/quarantine
WEBHOOK="https://your-webhook-url"

inotifywait -m -r -e modify,create,move,delete \
  --exclude '(uploads/|cache/|runtime/|logs/|\.log$|\.tmp$)' \
  "$SITE" | while read -r dir event file; do
    path="${dir}${file}"
    rel="${path#$SITE/}"
    ts=$(date '+%F %T')
    echo "[$ts] $event $path" >> /var/log/web_guard.log

    # 留存现场
    mkdir -p "$QUAR/$(dirname "$rel")"
    [ -f "$path" ] && cp -a "$path" "$QUAR/$rel.$(date +%s)"

    # 从可信源恢复
    if [ -e "$BASE/$rel" ]; then
      rsync -a --checksum "$BASE/$rel" "$path"
      action="已回滚"
    else
      rm -f "$path"
      action="已删除新增文件"
    fi

    curl -s -X POST "$WEBHOOK" -H 'Content-Type: application/json' \
      -d "{\"text\":\"[网页防篡改] $(hostname) $event $rel $action\"}" >/dev/null
  done

要点说明:

  • --exclude 用正则排除上传、缓存、日志目录,这是控制误报的关键。
  • 恢复前先 cp 到隔离区,保留取证样本,便于事后分析入侵路径。
  • 备份源不存在该文件时,说明是攻击者新增(如 webshell),直接删除而非保留。

四、用 systemd 托管并验证效果

写服务单元 /etc/systemd/system/web_guard.service:

[Unit]
Description=Web Tamper Guard
After=network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/web_guard.sh
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

启用并验证:

chmod +x /usr/local/bin/web_guard.sh
systemctl daemon-reload
systemctl enable --now web_guard
systemctl status web_guard

# 模拟篡改
echo 'hacked' >> /var/www/html/index.html
tail -f /var/log/web_guard.log

正常表现是:日志出现 modify 事件,文件被还原,告警消息送达。若没有反应,检查 inotifywait 是否递归生效、排除规则是否误伤。

五、误报控制与防护增强对比

纯监控容易陷入告警疲劳,需要按目录分级处理:

目录类型典型路径策略
代码与模板/var/www/html/*.php严格监控,变更即告警并回滚
上传目录/uploads排除监控,改为限制可执行权限
缓存与日志/cache /logs排除监控,仅做容量巡检

同时建议叠加:Web 目录对运行用户只读、定时用哈希清单做完整性比对、在边界部署 AegisX 的 WAF 能力拦截恶意上传与 webshell 访问,把「入口阻断」和「事后恢复」组合起来,单靠 inotify 只能发现不能预防。

六、上线检查清单

  • 备份源独立存放且只读,权限与站点目录分离。
  • 排除规则覆盖上传、缓存、日志、临时文件。
  • 告警接入即时通讯群,消息含主机名、路径、事件、动作。
  • 隔离区定期清理,保留至少 7 天取证样本。
  • 日志配置 logrotate,防止磁盘写满导致监控中断。
  • 每月做一次模拟篡改演练,确认恢复链路有效。

行动建议:先在测试站按上述脚本跑通「篡改—告警—回滚」全流程,再灰度到生产;发布流程与监控解耦,避免正常发版被误判。把网页防篡改做成常态机制,而不是出事后的临时救火。

常见问题(FAQ)

inotify 监控网站目录,服务器重启后脚本就没了怎么办?

用 systemd 托管即可。把监控脚本写成 service 单元,设置 Restart=always,执行 systemctl enable --now 开机自启。注意脚本内用绝对路径,并先确认 inotifywait 存在(yum/apt 安装 inotify-tools)。这样进程异常退出会被自动拉起,重启也不丢监控。

网站有用户上传和缓存目录,一改就告警,怎么减少误报?

在监控命令中用 --exclude 排除 uploads、cache、runtime、logs 等目录,或改用 --excludei 忽略大小写。更稳妥的做法是只监控代码与模板目录,把可变目录单独列出白名单。上线前先跑观察模式记录一天事件,再据此收敛规则,误报率会明显下降。

rsync 恢复会不会把正常更新也覆盖掉?

会,所以恢复必须区分场景。建议备份源保持只读,发布走独立流程;监控脚本只对白名单外的新增/修改文件触发恢复,并在恢复前把被改文件复制到隔离目录留证。对整站发布场景,可先暂停监控再发布,发布完成后重新启用。

只靠 inotify 告警够不够,还需要别的防护吗?

不够。inotify 属于事后发现,攻击者若拿到 root 可直接卸载或杀掉监控。建议叠加文件完整性校验(如定时比对哈希)、Web 目录只读挂载、最小权限运行 Web 服务,并在边界部署 WAF 拦截上传木马等入口行为,形成发现加阻断的组合。

告警发到哪里比较实用,邮件总是没人看?

优先发到即时通讯群机器人或短信,邮件只作归档。脚本里用 curl 调用 webhook 即可,消息中带上主机名、文件路径、事件类型和时间。关键目录变更设高优先级,普通变更合并成摘要每十分钟推送一次,避免告警疲劳。