limit_req_zone $binary_remote_addr zone=wplogin:10m rate=5r/m;
set_real_ip_from 10.0.0.0/8;
real_ip_header CF-Connecting-IP;
location = /wp-login.php {
limit_req zone=wplogin burst=3 nodelay;
limit_req_status 503;
}
access.log 里同一个境外段一分钟出现 1800 次 POST /wp-login.php,全部返回 200,后台多了几十个陌生账号。nginx 里 limit_req 明明配了,一个 503 都没有。这类现象通常不是突然出现的,往前翻半天日志能看到苗头。
追下去是这么回事:限速键用的是 $binary_remote_addr,站点前面挂着 CDN,nginx 看到的全是回源 IP,几千个请求落进同一个桶,桶早满了却只算一个客户端。真实 IP 要先用 real_ip_header 还原,顺序不能反。
围绕「wp-login 限速」排查时,命令行跑一遍比在面板里点十次有用,面板会替你做掉不少隐式操作。同一份配置存在多处的,先确认改的是被加载的那一份。
新版本先放一台机器上跑一天再全量,问题一般在这段时间暴露。
处理上按这个顺序:在 http 块里用 set_real_ip_from 信任 CDN 回源段,real_ip_header 写 CDN 传过来的那个头;单独给 wp-login.php 建一个限速 zone,速率按每分钟五次算,burst 给三就够;限速命中时返回 503,别用 429,WordPress 会把 429 当成普通失败继续重试。
确认没问题再收工,对着 wp-login.php 连打二十次,第四次开始返回 503,access.log 里的客户端 IP 已经是真实公网地址。
