根本原因是nginx未配置real_ip指令链信任cdn回源ip段并解析x-forwarded-for头,导致$remote_addr仍为cdn节点ip,进而使宝塔日志、防火墙及php的$_server['remote_addr']无法获取真实用户ip。

宝塔面板日志和防火墙看到的全是CDN节点IP,不是用户真实IP——根本原因是Nginx没正确识别并信任X-Forwarded-For头,且未配置real_ip指令链。
为什么宝塔后台显示的IP还是CDN的IP
即使CDN已透传X-Forwarded-For,Nginx默认不解析该头作为客户端IP;宝塔的Web防火墙、日志模块(access_log)、PHP的$_SERVER['REMOTE_ADDR']都依赖Nginx最终设置的$remote_addr变量。若没用set_real_ip_from和real_ip_header重写它,就永远拿不到真实IP。
常见错误现象:
– 宝塔“网站监控”里访问IP全是103.21.244.0这类Cloudflare或阿里云CDN网段
– 防火墙封禁IP无效,因为封的是CDN出口IP而非攻击者真实IP
– PHP中$_SERVER['REMOTE_ADDR']返回CDN节点IP,导致登录限流、地理判断失灵
必须配置的Nginx real_ip规则(宝塔生效版)
在宝塔面板中,进入「网站」→「设置」→「配置文件」,在server块内location /之前插入以下内容(注意替换为你的CDN实际回源IP段):
set_real_ip_from 103.21.244.0/22; set_real_ip_from 103.22.200.0/22; set_real_ip_from 103.31.4.0/22; set_real_ip_from 104.16.0.0/12; set_real_ip_from 108.162.192.0/18; set_real_ip_from 131.0.72.0/22; set_real_ip_from 141.101.64.0/18; set_real_ip_from 162.158.0.0/15; set_real_ip_from 172.64.0.0/13; set_real_ip_from 173.245.48.0/20; set_real_ip_from 188.114.96.0/20; set_real_ip_from 190.93.240.0/20; set_real_ip_from 197.234.240.0/22; set_real_ip_from 198.41.128.0/17; set_real_ip_from 2405:b500::/32; set_real_ip_from 2405:8100::/32; set_real_ip_from 2c0f:f248::/32; real_ip_header X-Forwarded-For; real_ip_recursive on;
关键说明:
– set_real_ip_from必须填CDN官方公布的**回源IP段**(如Cloudflare、腾讯云CDN、又拍云各有不同列表),不能只写一个IP
– real_ip_recursive on启用递归解析,才能从X-Forwarded-For: a, b, c中取最左边第一个非可信IP(即用户真实IP)
– 顺序不能错:必须先set_real_ip_from再real_ip_header,否则不生效
– 宝塔自带的“反向代理”配置不会自动加这些,必须手动贴进主配置
验证真实IP是否生效的三个动作
改完配置后别急着重启,按顺序做:
– nginx -t检查语法(宝塔终端执行,避免配置错误导致站点宕机)
– 在网站根目录放一个ip.php,内容为<?php echo $_SERVER['REMOTE_ADDR']; ?>,用curl带CDN头测试:curl -H "X-Forwarded-For: 1.2.3.4" https://yoursite.com/ip.php,应输出1.2.3.4而非CDN IP
– 查看Nginx访问日志:tail -f /www/wwwlogs/yoursite.log,刷新页面,确认日志首字段是用户真实IP(不是CDN段)
容易踩的坑:
– 忘记在宝塔「网站」→「SSL」→「强制HTTPS」开启状态下,CDN可能走HTTP回源,导致X-Forwarded-For被忽略(需确保CDN回源协议与Nginx监听协议一致)
– 使用了proxy_set_header X-Real-IP $remote_addr但没配real_ip指令,这只是透传,不是重写$remote_addr
– CDN控制台没开启“传递客户端真实IP”开关(如Cloudflare要开「Always Use HTTPS」+「IP Geolocation」,又拍云要勾选「透传客户端IP」)
PHP程序里还要注意的兼容点
即使Nginx已正确设置$remote_addr,部分PHP框架(如ThinkPHP、Laravel)仍会优先读$_SERVER['HTTP_X_FORWARDED_FOR'],而这个头可被伪造。所以:
– 不要直接信任$_SERVER['HTTP_X_FORWARDED_FOR'],应以$_SERVER['REMOTE_ADDR']为准(它已被Nginx重写)
– Laravel需在App\Http\Middleware\TrustProxies中配置$proxies为CDN网段,否则request()->ip()仍返回CDN IP
– WordPress插件如Wordfence、Sucuri依赖真实IP做拦截,必须确保其底层调用的是REMOTE_ADDR而非自解析X-Forwarded-For
真实IP这件事,本质是信任链问题:CDN → Nginx → PHP → 应用层,任何一环没对齐信任范围(IP段)或解析方式(recursive),就会断掉。最常被忽略的是CDN回源IP段更新——比如Cloudflare新增了IPv6段,但你配置里还只有旧的/32,那一部分用户IP就又变回CDN节点了。











