nginx需同时配置set_real_ip_from、real_ip_header和real_ip_recursive on,并确保fastcgi_param remote_addr $remote_addr,才能使php的$_server['remote_addr']获取用户真实ip。

realpath 和获取 CDN 真实 IP 完全无关。这是个常见误解——把 realpath(PHP 函数,用于解析文件路径)和 Nginx 的 real_ip 指令混淆了。配置 CDN 后拿不到真实 IP,问题一定出在 Nginx 的 IP 透传逻辑上,跟 PHP 路径函数毫无关系。
为什么加了 set_real_ip_from 还是拿到 CDN 节点 IP
最常踩的坑是:只写了 set_real_ip_from,但漏掉了 real_ip_header 或 real_ip_recursive on。Nginx 的 real_ip 系列指令必须成套出现,缺一不可。
-
set_real_ip_from告诉 Nginx “哪些 IP 是可信代理”,但它本身不触发任何解析行为 -
real_ip_header X-Forwarded-For才真正指定从哪个 HTTP 头读取原始 IP 列表 -
real_ip_recursive on决定怎么从X-Forwarded-For: a,b,c中取值:关掉就取最左(a),开了才从右往左跳过所有可信段,取第一个非 CDN IP - 三者必须写在
server {块最顶部、任何location之前,顺序无所谓,但位置错(比如塞进location /里)就完全不生效
CDN 回源 IP 段填 0.0.0.0/0 看似省事,实际埋雷
很多教程直接写 set_real_ip_from 0.0.0.0/0,等于告诉 Nginx:“所有 IP 都可信”。这会让攻击者伪造 X-Forwarded-For: 1.2.3.4 直接绕过所有 IP 校验。
- 务必去你所用 CDN 官方文档查真实回源 IP 段(Cloudflare、阿里云、腾讯云都公开列表)
- 例如 Cloudflare 的 IPv4 段是
173.245.48.0/20、103.21.244.0/22等,至少填 3–5 行,不能只写一个 - 填错或漏填会导致
real_ip_recursive on失效——它依赖set_real_ip_from的匹配结果来“跳过”可信段
PHP 里 $_SERVER['REMOTE_ADDR'] 还是 CDN IP?检查 FastCGI 透传
Nginx 改完 $remote_addr 只是第一步。PHP 能否拿到,取决于是否把新值通过 FastCGI 传给 PHP-FPM。
- 打开站点配置文件,搜索
fastcgi_param REMOTE_ADDR - 确认它被设为
$remote_addr,而不是$http_x_forwarded_for或硬编码值 - 宝塔默认有这行,但如果你用过自定义模板、或手动删改过,很可能已被破坏
- 临时加个调试页:
<?php var_dump($_SERVER['REMOTE_ADDR'], $_SERVER['HTTP_X_FORWARDED_FOR'] ?? 'none');,输出应为「你的真实公网 IP」+「逗号分隔的一串 IP」
X-Forwarded-For 安全提取真实 IP;PHP 必须收到这个提取后的 $remote_addr,而不是原始连接 IP。中间任何一环断掉,$_SERVER['REMOTE_ADDR'] 就永远是 CDN 节点地址。











