先看现象。迁移到 CDN 后源站改用 X-Forwarded-For 取真实 IP 做限流,结果所有请求的头都被边缘节点改写成一个内网地址,蜘蛛第一个被封。
排查方向其实有限,先把可能性排一排。边缘节点把 XFF 覆盖成自己的地址,源站看到的是同一个 IP。少数情况下是限流阈值按单 IP 设得很低,聚合后瞬间触发。
还有一种情况,源站没有校验代理层的可信来源,头可以被任意伪造。
另外,封禁时间设成 24 小时,蜘蛛当天再也没回来。
动手时先看 Nginx 记到的真实 IP
tail -100 access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head
直接请求源站确认头的内容
curl -sI -H 'X-Forwarded-For: 66.249.66.1' https://origin.example.com/ | grep -i forwarded
然后改用 real_ip 模块并指定可信代理
set_real_ip_from 10.0.0.0/8; real_ip_header X-Forwarded-For; real_ip_recursive on;
末了把封禁时长改成 10 分钟
limit_req_zone $binary_remote_addr zone=api:10m rate=20r/s;
怎么算真的好了,看的是同一批现象。日志里重新出现蜘蛛的真实 IP 段,限流只对异常单 IP 生效,抓取量恢复到迁移前水平。
取真实 IP 要信任代理链而不是信任请求头,否则限流规则会先打在自己人身上。这类问题最好一次改到位,反复小改反而容易把原因搅混。
