这类问题我又碰上了一次。站点前面挂了两层代理,第一层是 CDN,第二层是自建 Nginx。日志里的 $http_x_forwarded_for 只记了客户端 IP,真实蜘蛛地址被写在第二段,按 IP 反查归属时整批判成家宽。

第一反应是「日志只打 $http_x_forwarded_for,没有单独记录 $remote_addr」,验证下来不成立。

原因不止一个,得分开看。CDN 回源时覆盖而不是追加 XFF,源站只看到边缘写的那一个地址;中间层用了 proxy_set_header X-Forwarded-For $remote_addr,上游链整段丢掉;real_ip 模块没配 set_real_ip_from,$remote_addr 一直是代理 IP。

第一件事是看日志里 XFF 到底有几段

awk -F'"' '{print $NF}' access.log | head

随后改成追加而不是覆盖

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

接着启用 real_ip 并指定可信代理段

set_real_ip_from 203.0.113.0/24; real_ip_header X-Forwarded-For; real_ip_recursive on;

日志里同时记录两个字段

log_format realip '$remote_addr $http_x_forwarded_for $request $status';

改之前我把相关日志按时间截了一段存着,事后对时间线用得上。

改完先别撤,确认这几项。改完后 $remote_addr 已经是蜘蛛真实 IP,反查归属能对上官方网段,按 IP 聚合的抓取量不再集中在少数节点上。

多层代理下 XFF 是从客户端到边缘依次追加,取错一段就会把整份统计带偏。报错文案容易误导,真正的原因往往在相邻那一层的日志里。

作者 9823189