Nginx+PHP网页防篡改方案对比:文件监控、WAF与只读挂载 核心要点图解,只读挂载防篡改最彻底,但需配合发布流程改造,适合静态资源与模板目录。;文件监控负责发现,WAF 负责拦截,两者互补而非替代。;Nginx 层禁用上传目录 PHP 执行,是成本最低的兜底措施。;防篡改核心是缩短发现时间与可回滚,而非追求零改动。
Nginx+PHP网页防篡改方案对比:文件监控、WAF与只读挂载 · 核心要点一图读懂(AegisX)

核心要点(TL;DR)

  • 只读挂载防篡改最彻底,但需配合发布流程改造,适合静态资源与模板目录。
  • 文件监控负责发现,WAF 负责拦截,两者互补而非替代。
  • Nginx 层禁用上传目录 PHP 执行,是成本最低的兜底措施。
  • 防篡改核心是缩短发现时间与可回滚,而非追求零改动。

凌晨两点,首页被换成黑页,搜索引擎快照里还挂着赌博链接——这是运维最不想接到的电话。Nginx+PHP 站点被篡改,通常不是漏洞有多高级,而是文件被改了却没人第一时间知道。本文对比文件监控、WAF、只读挂载三种网页防篡改思路,给出可直接复制的命令与上线检查清单,帮你在当天完成第一层防护。

三种方案到底在防什么

先明确边界,避免买错药:

  • 文件监控:解决“发现”。基于 inotify 或哈希基线,文件一变就告警,属于事后但最快的手段。
  • WAF:解决“拦截”。在 HTTP 层挡住上传 Webshell、SQL 注入等入侵路径,属于事前。
  • 只读挂载:解决“兜底”。把代码目录挂成只读,即使拿到 shell 也写不进去,属于事中阻断。

三者不是替代关系。只上 WAF,攻击者用 SSH 弱口令登进来照样改文件;只做只读,发布流程会立刻卡住。合理做法是分层组合。

方案一:文件监控,先建立基线再谈告警

没有基线的监控等于没有监控。先在发布完成后生成哈希清单:

find /var/www/html -type f \( -name '*.php' -o -name '*.html' -o -name '*.js' \) \
  -not -path '*/cache/*' -print0 | xargs -0 sha256sum > /opt/baseline.sha256

再部署实时监控脚本,只盯代码与模板目录:

inotifywait -m -r -e modify,create,delete,move \
  --exclude '(cache|logs|uploads)' \
  --format '%T %w%f %e' --timefmt '%F %T' \
  /var/www/html >> /var/log/web_tamper.log

注意两点:大站点需调大 fs.inotify.max_user_watches;日志要接入告警通道,否则文件只是安静地写进磁盘。发现变更后,用 sha256sum -c /opt/baseline.sha256 比对,非发布窗口内的不匹配项优先按入侵处理。

方案二:WAF,把上传目录的执行权限关掉

很多篡改源头是上传目录里的 PHP 被直接访问执行。Nginx 层一条配置就能堵住大部分:

location ~* ^/(uploads|images|attach)/.*\.(php|phtml|php5)$ {
    deny all;
    return 403;
}

同时收紧可写范围,只允许必要目录被 PHP 写入:

location ~ \.php$ {
    fastcgi_pass unix:/run/php/php8.1-fpm.sock;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include fastcgi_params;
}

规则型 WAF(如 ModSecurity + OWASP CRS)能补拦截层,但要预留调优时间,误杀会直接打挂业务。若使用 AegisX 的防护能力,可把 Web 攻击拦截与文件完整性告警放在同一控制台,缩短从告警到处置的路径。

方案三:只读挂载,最彻底也最考验发布流程

把代码目录挂成只读,攻击者即使拿到 www-data 权限也无法落盘:

mount --bind /var/www/html /var/www/html
mount -o remount,ro,bind /var/www/html

写入 /etc/fstab 固化:

/var/www/html /var/www/html none bind,ro 0 0

代价是发布流程必须改造:卸载只读、同步、重新挂载。建议封装脚本,并只对静态资源、模板、代码目录只读,cache、logs、session 单独挂可写,否则 PHP 会因写日志失败报错。

三种方案对比与选型

维度文件监控WAF只读挂载
作用阶段事后发现事前拦截事中阻断
部署成本低,几十行脚本中,需规则调优中,需改发布流程
性能开销低到中中几乎为零
主要风险告警疲劳误杀业务发布失败

选型建议:中小站点先做 Nginx 加固 + 文件监控;有合规要求或攻击面大的站点补 WAF;静态资源与模板目录优先只读。

上线检查清单

  1. 代码目录已生成 sha256 基线并纳入版本管理。
  2. inotify 监控覆盖代码与模板,已排除 cache/logs/uploads。
  3. 上传目录 PHP 执行已返回 403。
  4. 可写目录仅限 cache、logs、session、uploads。
  5. 只读挂载有对应发布脚本,回滚步骤已演练。
  6. 告警接入值班通道,明确 15 分钟内响应。

行动建议:今天先完成第 1、2、3 项,成本最低、收益最直接;本周内补齐只读挂载与发布脚本。网页防篡改的目标不是零改动,而是改动可控、异常可见、回滚可执行。

常见问题(FAQ)

网页防篡改只装 WAF 够不够?

不够。WAF 主要拦截外部入侵路径,如 SQL 注入、文件上传 Webshell,但无法阻止攻击者通过 SSH、弱口令或供应链进入后直接改文件。网页防篡改需要“入口拦截 + 文件变更发现 + 只读兜底”三层配合,WAF 只是第一层,缺少文件监控时篡改可能数天都无人发现。

只读挂载会不会影响网站正常更新?

会影响,但可控。只读挂载后发布流程必须改为“卸载只读—同步文件—重新挂载”,建议用脚本封装成一条发布命令,并在维护窗口执行。静态资源、模板、上传目录适合只读;需要频繁写入的缓存、日志、session 目录应单独挂载为可写,避免整站只读导致 PHP 报错。

inotify 监控大量文件会不会拖慢服务器?

取决于监控范围与事件频率。默认 inotify 上限为 8192 个 watch,大站点需调大 fs.inotify.max_user_watches。建议只监控代码与模板目录,排除 cache、logs、uploads,并用 inotifywait 的 --exclude 过滤;单机十万级文件以内开销通常可接受,更高量级应改用审计日志或集中式文件完整性工具。

怎么判断告警是正常发布还是被篡改?

靠基线哈希与发布记录比对。上线前对代码目录生成 sha256 清单并纳入版本管理,监控脚本发现变更后自动比对哈希与最近一次发布记录;不在发布窗口内、哈希不匹配、且文件属主异常(如 www-data 可写)的变更优先按入侵处理,先隔离样本再回滚。

中小站点预算有限,优先做哪一项?

优先做 Nginx 层加固加文件监控。禁用上传目录 PHP 执行、限制可写目录、关闭不必要的目录浏览,成本几乎为零;再用 inotifywait 脚本对代码目录做变更告警,几十行脚本即可上线。只读挂载与 WAF 可在业务稳定后逐步补齐,形成分层防护。