Nginx速率限流完全失效,请求排查解决
嘿,我来帮你捋捋这个Nginx限流失效的问题!你的需求很明确:不想让黑客瞎扫服务器上的PHP文件(毕竟你们完全不用PHP),而且因为用了Cloudflare代理,已经配置了realip来拿真实客户端IP,但现在限流就是不生效,对吧?
我从几个最可能的问题点给你一步步排查:
1. 先补全RealIP配置的关键项
你已经把Cloudflare的IP段都加进set_real_ip_from里了,但漏掉了最核心的一行!Cloudflare是通过CF-Connecting-IP这个HTTP头来传递真实客户端IP的,你得明确告诉Nginx用这个头替换默认的remote_addr——不然Nginx会把Cloudflare的节点IP当成客户端IP来限流,那肯定失效啊,所有请求看起来都来自少数几个Cloudflare IP,根本达不到你设置的限流阈值。
赶紧在你的http块里补上这行:
real_ip_header CF-Connecting-IP;
2. 配置正确的限流规则逻辑
你没贴具体的限流规则,我猜大概率是规则位置不对或者逻辑有问题,给你一套完整的可落地配置:
第一步:在http块定义限流共享内存区
# 用二进制存储IP节省空间,10M内存大概能存几十万个IP;rate=10r/m表示每分钟允许10个PHP请求,可按需调整 limit_req_zone $binary_remote_addr zone=php_scan:10m rate=10r/m;
第二步:在server块配置PHP文件的限流规则
location ~* \.php$ { # 如果你确定完全不用PHP,直接对所有PHP请求限流+返回429(比403更标准,明确告诉请求方“请求过多”) limit_req zone=php_scan burst=5 nodelay; return 429; # 要是怕以后突然有合法PHP文件,也可以加判断:只对不存在的PHP文件限流 # if (!-f $request_filename) { # limit_req zone=php_scan burst=5 nodelay; # return 429; # } # return 404; }
这里的burst=5是允许5个突发请求,nodelay表示超过阈值后直接拒绝、不排队,避免黑客短时间内扫大量文件。
3. 验证真实IP是否被正确获取
配置完后一定要确认Nginx拿到的是真实客户端IP,而不是Cloudflare的节点IP。你可以修改日志格式,把相关信息打出来:
log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_cf_connecting_ip"';
重启Nginx(nginx -s reload)后,随便访问几个PHP文件,看日志里的$remote_addr和$http_cf_connecting_ip是否一致:
- 一致:说明RealIP配置生效了
- 不一致:检查Cloudflare是不是开了代理模式(不是DNS Only)、有没有重启Nginx、有没有其他模块(比如geo)修改了
remote_addr导致冲突
4. 测试限流是否生效
找个真实的客户端IP(别用Cloudflare节点IP),快速刷新多个不存在的PHP文件,看看是不是会返回429错误——如果达到阈值后开始拦截,说明限流生效了。
备注:内容来源于stack exchange,提问作者Kevin Renskers

