分布式撞库下 IP 限速的边界
Nginx limit_req 限制 WordPress 登录入口频率:阈值设定、白名单与误封回滚清单
给 WordPress 站点加登录限速的人,多半会经历同一个落差:配置改完,日志里 429 开始冒出来,心里先松一口气;过几天再翻,登录失败记录还在涨,反倒是同事在群里问后台为什么打不开。
这中间的差距,就是 IP 限速本身的天花板。它管的其实不是“有人撞库”这件事,而是“同一个来源打得太快”这件事。
限速拦的是单点,不是组织
Nginx 的请求限速按 key 计数,这个 key 通常是客户端 IP。它用的是一个漏桶模型:rate 决定稳态放行速度,burst 决定临时能多挤进几个,两者配合着把某一来源的高频请求压下来。
问题就在这儿。分布式撞库的思路恰恰是不让任何一个 IP 打得太快:手里攥着一堆地址,每个只试几次,摊薄到全网,绝大多数请求都落不进阈值里。规则照常生效,攻击照常继续。所以按 IP 限速压得住的是单点高频的机器流量,压不住有组织的分布式尝试。指望它彻底阻断撞库,方向就错了。
真正先中枪的往往是自己人
限速最容易出事的地方不在参数,在“谁被算作同一个来源”。
一个典型的坑是站点前面挂了 CDN 或反向代理。这时候拿到的地址是边缘节点的地址,不是真实访客的地址——等于把全站访客挤进同一个计数器,一限就是全员。上规则前先去日志里确认记录的客户端 IP 是不是真的,比事后排查省事得多。
另一类是同一个人群的共用出口。办公网络、运维跳板常常共用一个出口地址,多个编辑者从这个地址登录,频率叠起来很容易踩线。这类地址该走白名单,而不是靠把 rate 调大来迁就——调大之后,攻击者也一起被放进来。白名单的做法也不是写一堆放行规则,而是让被豁免的请求干脆不进入计数,不占用那个计数器。
用日志反推阈值松紧
阈值不该凭印象定,日志里其实写得很清楚。被拦下来的 IP 如果集中在少数几个网段,而且这些网段确实有真人反映受影响,那就是白名单没覆盖全;如果被拦的 IP 极其分散、每个只出现一两次,那多半不是攻击集中,而是阈值本身偏紧,该往上调一档。
这两种情况处置方式完全相反,所以先看分布,再动手。
说到底,IP 限速在登录防护里是一层筛子,不是一堵墙。它的价值有两个:把明显的机器流量挡在 PHP 之外,减少后端被无效请求拖住的机会;把剩下的可疑请求留在日志里,让它们可追溯、可分析。至于登录本身的安全,还得靠强口令、双因素、失败锁定这些措施一起上。而这一层要发挥价值,前提是它能被验证,也能被回滚——改之前先想清楚怎么退回去,比改得多漂亮更重要。

参与讨论
之前踩过 CDN 拿不到真实 IP 的坑