日志里全是机房 IP:realip 到底怎么还原
挂上 CDN 的第二天我发现两件事:访问日志里全是同一批机房 IP,nginx 的限速也变成了随机伤人——明明是别人打你,偶尔被封的却是正常用户。
原因就一个:$remote_addr 已经不是访客的地址了。
问题长什么样
162.158.88.31 - - [28/Oct/2026:10:12:03 +0800] "GET / HTTP/2.0" 200
162.158.88.31 - - [28/Oct/2026:10:12:04 +0800] "GET /assets/css/style.css" 200
172.71.150.6 - - [28/Oct/2026:10:12:05 +0800] "GET /post.html" 200
这些都是 CDN 的回源节点。日志看不出谁在访问,limit_req 也会把它们当成同一个来源。
修法:让 nginx 信任 CDN 网段
# /etc/nginx/snippets/cf-realip.conf
set_real_ip_from 173.245.48.0/20;
set_real_ip_from 103.21.244.0/22;
# … 其余网段用脚本生成,别手抄:CDN 会新增网段
real_ip_header CF-Connecting-IP;
real_ip_recursive on;
然后在 server 块里 include 它。
三个关键点:
set_real_ip_from是白名单。只有这些网段发来的CF-Connecting-IP才会被采信,所以别人伪造这个头没有用。real_ip_recursive on配合单一 header 才好用;如果 CDN 传的是X-Forwarded-For链,它决定了从右往左信任到哪一跳。- 段列表要能自动更新。我写了个脚本拉官方列表生成 snippet,失败时用内置列表兜底,这样不会因为网络问题把 nginx 配坏。
最容易踩的三个坑
一、zone 定义了但没生效。 limit_req_zone 必须写在 http 级。放 server 里 nginx -t 直接报错,或者你以为是全局的其实只对某个站点生效。
二、realip 没 include 进这个 server。 症状很隐蔽:日志还是机房 IP,但限速"看起来在工作"。实际是所有访客共用一个桶。
三、所有访客一起被 429。 这是 realip 失败最危险的表现。20 个人同时用你的站,看起来像被打了。判断方法:临时在 server 里加 add_header X-Debug-IP $remote_addr always;,看返回的头是不是自己的出口 IP。
验证
# 用手机 4G 打开站点,然后本机看日志
tail -f /var/log/nginx/blog.access.log
# 应该出现你手机的出口 IP,不再是 162.158.x / 172.71.x
反过来再验一次"直连会不会被误判":从非 CDN 网段直接请求源站 IP,看 $remote_addr 是不是对方真实地址、有没有被 set_real_ip_from 之外的值改写。
注意
realip 生效之后,你的限速、封禁、日志统计才第一次变准。所以它是所有"按 IP 做策略"的前提,不是可选项。
需要按上面的步骤在自己服务器上配一遍? 可以邮件 2725854295@qq.com,或者关注公众号「凌的科技圈」留言。说明系统版本和域名,我给一套现成的配置文件。