站点接了 CDN 之后,nginx 访问日志里所有请求的来源 IP 都变成了 127.0.0.1 或者 100.64.x.x。

后果很直接:蜘蛛统计失效、CC 防护失效、封 IP 封错人、nginx 的限流全打在 CDN 节点上。

一、为什么会这样

HTTP 请求经过 CDN 之后,TCP 连接对端变成了 CDN 节点,不是真实用户。

nginx 的 $remote_addr 取的是 TCP 对端地址,所以它看到的是 CDN 节点 IP。

真实 IP 藏在请求头里:

X-Forwarded-For: 223.240.58.51, 172.68.1.1

这个头是逗号分隔的链:最左边是客户端,最右边是最后一级代理。

二、nginx realip 模块

nginx 自带 ngx_http_realip_module,作用是从指定请求头里取 IP,覆盖 $remote_addr。覆盖之后,日志、限流、deny 规则全都会用真实 IP。

配置放在 http 块或者 server 块里:

set_real_ip_from 172.68.0.0/16;
set_real_ip_from 104.16.0.0/13;
real_ip_header X-Forwarded-For;
real_ip_recursive on;

三行分别的意思是:

  • set_real_ip_from:只信任这些段的请求头,可以写多行
  • real_ip_header:从哪个头取 IP
  • real_ip_recursive on:从右往左找第一个不在信任段里的 IP

三、安全:这是最容易出错的一步

如果不配 set_real_ip_from 就开 real_ip_header,等于把 IP 的判定权交给用户。

任何人发一个 X-Forwarded-For: 8.8.8.8,就能把自己伪装成谷歌 DNS。你的封禁、限流、统计全部被绕过。

所以必须先拿到 CDN 的官方段。Cloudflare 的:

curl -s https://www.cloudflare.com/ips-v4

输出几十个段,写进配置或者用 include 引进来:

include /www/server/nginx/conf/cloudflare_ips.conf;

CDN 段会变,建议挂个定时任务每周拉一次,不然新节点上线后你就不认了。

四、日志格式要不要改

经常看到有人这么干:

log_format main '$http_x_forwarded_for - $remote_user ...';

不要这么写。两个问题:

  1. XFF 是逗号分隔的链,不是单个 IP。后面所有按 IP 统计的命令全部失效
  2. XFF 可以被伪造,日志里会混进假 IP,事后取证没法用

正确做法是配好 realip,让 $remote_addr 自动变成真实 IP,日志格式一个字都不用改。

五、验证

配完重载,然后从外网访问一次:

nginx -t && nginx -s reload
tail -f /www/wwwlogs/你的域名.log

看第一条记录的 IP 是不是你自己的宽带 IP。

还可以手动伪造一个头,验证信任链有没有生效:

curl -H "X-Forwarded-For: 1.2.3.4" https://你的域名/

如果日志里出现 1.2.3.4,说明 set_real_ip_from 没生效,或者范围写宽了——你的请求不来自 CDN,本来不应该被信任。

六、宝塔用户注意

宝塔的网站配置里,include enable-php-81.conf; 这些是自动生成的,手动改会在面板保存时被覆盖。

放这两个位置不会被覆盖:

  • /www/server/panel/vhost/nginx/你的域名.conf 的 server 块(改完别在面板点"保存配置")
  • /www/server/panel/vhost/nginx/extension/你的域名/*.conf(推荐,面板根本不动这个目录)

七、还有一个坑:IPv6

如果站点同时开了 IPv6,CDN 回源可能走 v6。这时候日志里是 ::1 或者 ::ffff:127.0.0.1。

realip 模块对 v6 也管用,但 set_real_ip_from 要写 v6 的段:

set_real_ip_from 2400:cb00::/32;
set_real_ip_from 2606:4700::/32;

只配了 v4 段的话,v6 回源的请求还是拿不到真实 IP。

现象 原因 解决
日志 IP 全是 127.0.0.1 同机反代,回源走本地 配 realip
日志 IP 全是 CDN 段 没配 realip 配 set_real_ip_from
日志里混进 8.8.8.8 XFF 被伪造,信任范围太宽 收窄 set_real_ip_from
日志 IP 是 ::1 只配了 v4 段 补 v6 段

日志里的 IP 是所有安全策略的地基。地基错了,上面盖多少层防护都没用。

俗人源码网免责声明:

1、本站所有资源均收集于互联网,分享目的仅限学习与参考。如有侵权,请联系 1685698671@qq.com 及时删除!

2、本站资源不保证完整性和安全性,下载后请自行检测。使用过程中出现的任何问题均与本站无关,敬请自行处理。

3、本站资源仅限个人学习研究使用,严禁用于任何违法违纪用途。因使用者违规使用产生的一切后果,由使用者自行承担,本站不承担任何责任。