本文记录了一次由 WordPress 优化插件 Autoptimize 引起的服务器资源异常消耗问题。通过日志分析,发现攻击者利用畸形请求 (/data:text/javascript…) 绕过正常的静态文件处理,强制触发 php-fpm 启动 WordPress 进程,最终在 Autoptimize 插件的高强度计算下导致服务器 CPU 资源被瞬间占满。解决方案核心在于修改 Nginx 配置,在 Web 服务器层面精准拦截并拒绝处理这些畸形请求。
一、故障描述
老王的一台 Linux 服务器,配置不高 2C4G,从昨天开始 php-fpm 的进程数和 CPU 占用率突然飙升至 100%,导致网站访问缓慢甚至超时(出现大量的 50x 或 499 错误):
这是我的环境配置:
-
CMS: WordPress
-
缓存: WP Super Cache (页面缓存)
-
优化: Autoptimize (CSS/JS 合并与压缩)
-
服务器: Nginx + PHP-FPM (LNMP 架构)
这个问题非常奇怪,只要启用 Autoptimize 插件,资源就会立即耗尽;一旦禁用 Autoptimize,资源使用量立刻恢复正常。
二、问题发现与定位
查看了网站的日志文件,日志文件里本身有很多垃圾请求,包括但不限于扫描 zip、暴力破解 login.php、xmlrpc.php 等,甚至还有很多僵尸 IP 来请求我的静态文件,不知道是想消耗我的流量还是什么,毕竟这种直接访问静态文件的请求对服务器资源的消耗并不算大。
后来在流水般的日志里找到了某些畸形请求:
| 异常点 | 日志示例 | 状态码分析 |
| 畸形 URL | GET /data:text/javascript;base64,Ci8qIDwh... |
浏览器使用的 Data URI 编码被爬虫当成了 URL 路径。 |
| 高并发中断 | ... HTTP/2.0" 499 0 ... |
状态码 499 (Client Closed Request) 表明客户端因服务器响应太慢或处理超时而主动断开连接,证实 PHP 进程被卡死。 |
这些 /data:text/javascript 的请求并非服务器上的实际文件,它们是畸形且无效的 URL,但是并没有立即返回 404,而是触发了高负载的 PHP 进程。
这个问题并非出在 Autoptimize 本身,而是出在 Nginx 错误处理机制与 Autoptimize 的工作模式相结合的“死亡循环”上。
在 WordPress Nginx 配置中,通常有一个 try_files 规则将所有找不到的文件(404)转发给 WordPress 的核心文件 index.php 来处理:
location / {
try_files $uri $uri/ /index.php?$args;
}
当畸形请求 /data:text/... 进来时,Nginx 找不到这个文件,于是它将控制权交给了 index.php。这便是 404 穿透 (404 Passthrough)。
这是如果你激活了 Autoptimize 插件,那么就会进行如下操作:
-
启动 PHP: 每一次 404 穿透都会强制启动一个 PHP-FPM 进程,加载 WordPress 核心程序。
-
插件介入: Autoptimize 在 WordPress 渲染页面(即使是 404 页面)的过程中介入,试图分析、合并、压缩 CSS 和 JS 文件。
-
资源耗尽: 面对大量的并发畸形请求,PHP 进程不断尝试执行耗费 CPU 的聚合运算,很快就占满了 PHP-FPM 的资源池,导致服务器瘫痪。
如果并发高,或者 Autoptimize 试图处理那个超长的 URL字符串,CPU 瞬间飙升。
三、解决方法
知道了问题,那么解决起来就简单了。
由于恶意请求的特征是 URL 包含 : 且以 /data: 开头,我们利用 Nginx 的 location 规则进行精准拦截。
# 1. 精准拦截 Data URI 畸形请求
# 匹配以 /data: 开头的 URL,直接返回 404,防止其进入 WordPress
location ~* ^/data: {
access_log off; # 无需记录这类垃圾日志
return 404; # Nginx 直接返回 404,不启动 PHP
}
同时,为了防止其他类型的静态文件 404 (如不存在的图片或 JS) 穿透,我们必须在静态资源 location 块中加入 try_files $uri =404;:
# 2. 静态文件防穿透 + 缓存优化
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|js|css|ico|woff|woff2|ttf|svg|eot)$ {
expires 30d;
access_log off;
log_not_found off;
# 核心指令:找不到文件,立即返回 Nginx 404,不回源到 PHP
try_files $uri =404;
}
最后执行 nginx -s reload 重载 Nginx 配置。资源占用率将立即恢复正常。
题外话:再应用了新配置后,攻击无效(直接返回 404),攻击者大概 5 分钟就停止这些畸形 URL 请求了,真的是闲的蛋疼。







