适用场景
- access.log 中出现大量
POST /wp-login.php请求,来源 IP 分散且全天持续 - 带宽被
POST /xmlrpc.php的 pingback 请求占满,或该路径请求量异常激增 - WordPress 站点未接入 WAF,希望用 Nginx 层配置直接封堵爆破与攻击放大
前置条件
- WordPress 站点运行于 Nginx(规则同样适用于宝塔等面板环境,写入站点配置文件即可)
- 拥有服务器 root 权限或面板配置文件编辑权限
- 明确站点是否依赖 JetPack、WordPress 手机客户端等使用 XML-RPC 的功能
原理说明
wp-login.php 是 WordPress 唯一的登录入口,攻击者用常见账号密码组合字典高频提交即可尝试爆破;由于请求是合法 POST,仅靠 WordPress 自身没有任何速率限制。xmlrpc.php 提供的 system.multicall 接口允许一次请求打包数百组账号密码尝试,把爆破效率放大百倍以上,其 pingback 功能还可被第三方借用发起放大攻击。两者的共同解法是在 Web 服务器层加限制:对登录页做基于 IP 的限流,对 xmlrpc.php 直接返回 403 或同样限流。
操作步骤
1. 定义限流区域
在 Nginx 主配置的 http 块中添加:
limit_req_zone $binary_remote_addr zone=wplogin:10m rate=10r/m;
limit_req_zone $binary_remote_addr zone=xmlrpc:10m rate=1r/m;
rate=10r/m 表示每个 IP 每分钟最多 10 次登录请求,人类正常操作完全够用,脚本爆破则会被直接拖垮。
2. 站点配置中应用限流并禁用 XML-RPC
server {
...
location = /wp-login.php {
limit_req zone=wplogin burst=5 nodelay;
limit_req_status 429;
include snippets/fastcgi-php.conf; # 按站点原有 fastcgi 配置填写
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
}
location = /xmlrpc.php {
# 若确认无任何功能依赖 XML-RPC,直接返回 403:
return 403;
}
}
登录页的 location 必须保留原有的 fastcgi 配置,否则登录页会变成下载 PHP 源码。若站点仍在使用 XML-RPC 相关功能,把 return 403 换成 limit_req 限流方案即可。
3. 登录失败锁定(应用层补充)
Nginx 限流按请求频率计算,无法识别慢速爆破。可在主题 functions.php 中增加失败锁定逻辑:
add_filter('authenticate', function($user, $username, $password){
if (is_wp_error($user)) {
$key = 'fl_' . md5($_SERVER['REMOTE_ADDR']);
$fails = (int) get_transient($key);
if ($fails >= 5) {
return new WP_Error('locked', '尝试次数过多,请 30 分钟后再试');
}
set_transient($key, $fails + 1, 30 * MINUTE_IN_SECONDS);
}
return $user;
}, 30, 3);
该逻辑对同一 IP 连续失败 5 次后锁定 30 分钟,与 Nginx 限流形成两层防线。
4. 重载 Nginx
nginx -t && nginx -s reload
配置验证
# 限流验证:短时间内连续提交登录请求,观察返回码
for i in $(seq 1 15); do
curl -s -o /dev/null -w "%{http_code}\n" -X POST https://www.example.com/wp-login.php
done
# 前几次为 200 或 302,超出速率后应出现 429
XML-RPC 验证:curl -s -o /dev/null -w "%{http_code}" https://www.example.com/xmlrpc.php,应返回 403。最后用浏览器正常登录一次,确认真实用户未被限流误伤。
常见问题
FAQ 1:禁用 XML-RPC 会影响什么功能?
JetPack 及其配套的站点统计、自动发布,以及 WordPress 手机 App 的应用密码登录、部分第三方同步工具依赖 XML-RPC。若在使用这些功能,保留限流方案而非 return 403,并在设置中单独关闭 pingback。纯内容展示型站点绝大多数可以直接禁用。
FAQ 2:配置后 wp-login.php 变成下载 PHP 文件?
原因是新加的 location 块漏掉了 fastcgi 配置,Nginx 把 PHP 文件当静态资源返回。将站点原有 location ~ \.php$ 块内的 include 与 fastcgi_pass 两行复制进新 location,或改用嵌套写法把限流指令放进原有 PHP location 内。
FAQ 3:自己被限流锁在外面了怎么办?
先换网络或用服务器本地 curl 验证是否为限流触发;确认后临时调大 rate 或注释限流行后 reload。办公网多用户共享出口 IP 会聚合触发限流,必要时用 map 把管理 IP 映射到独立 key 或直接放行,再恢复限流规则。
总结
WordPress 登录加固的核心是在 Web 服务器层收紧入口:limit_req 对 wp-login.php 做每分钟个位数的请求限制,xmlrpc.php 无依赖时直接 403、有依赖时限流,再叠加应用层失败锁定应对慢速爆破。配置后用 curl 批量请求验证 429 与 403 是否生效,并确认 fastcgi 配置完整。这三层措施实施成本低,能拦截绝大多数自动化爆破流量。