站点接了 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:从哪个头取 IPreal_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 ...';
不要这么写。两个问题:
- XFF 是逗号分隔的链,不是单个 IP。后面所有按 IP 统计的命令全部失效
- 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、本站资源仅限个人学习研究使用,严禁用于任何违法违纪用途。因使用者违规使用产生的一切后果,由使用者自行承担,本站不承担任何责任。


评论(0)