nginx 默认 $remote_addr 仅反映直连ip,经cdn/slb/反代时需配置 set_real_ip_from、real_ip_header 及 real_ip_recursive,并在php中直接使用 $_server['remote_addr'](已由nginx修正),日志应优先用 $realip_remote_addr。

直接说结论:Nginx 默认的 $remote_addr 只能拿到客户端直连 IP,如果前端有 CDN、SLB 或反向代理,必须靠 X-Forwarded-For(或 X-Real-IP)+ Nginx 配置 + PHP 主动读取三者配合,缺一不可;否则 PHP 中 $_SERVER['REMOTE_ADDR'] 永远是上一级代理的 IP。
为什么 $remote_addr 不可靠?
它只反映 TCP 连接发起方的 IP —— 在有 CDN、WAF、负载均衡器或公司内部反代时,这个值就是 CDN 节点、LB 机器或 Nginx 自身的内网 IP,不是真实用户 IP。常见现象包括:
- 所有访问日志里
$remote_addr都是同一个内网地址(如10.0.1.5) - PHP 中
$_SERVER['REMOTE_ADDR']固定为127.0.0.1或云厂商 LB 内网 IP - 基于 IP 的限流、封禁、地域判断全部失效
Nginx 必须设置 set_real_ip_from 和 real_ip_header
光在 upstream 里加 proxy_set_header X-Real-IP $remote_addr 没用。Nginx 要“信任”某个来源的 X-Forwarded-For,得显式声明可信代理段。否则 $realip_remote_addr 不会更新,log_format 里用 $remote_addr 依然错。
正确做法:
立即学习“PHP免费学习笔记(深入)”;
- 在
http或server块中添加可信代理网段:set_real_ip_from 10.0.0.0/8;<br>set_real_ip_from 172.16.0.0/12;<br>set_real_ip_from 192.168.0.0/16;<br>set_real_ip_from 127.0.0.1;
- 指定从哪个 header 提取真实 IP:
real_ip_header X-Forwarded-For;(CDN 通用)或real_ip_header X-Real-IP;(部分自建反代习惯用) - 可选但推荐:
real_ip_recursive on;,让 Nginx 递归解析X-Forwarded-For最左非可信 IP(例如X-Forwarded-For: 203.0.113.5, 198.51.100.2, 10.0.1.3,若最后一个是可信代理,则取198.51.100.2)
PHP 中不能直接信 $_SERVER['HTTP_X_FORWARDED_FOR']
这个值可能被客户端伪造,Nginx 未做清洗前直接用极不安全。正确方式是依赖 Nginx 注入的 $_SERVER['REMOTE_ADDR'] —— 它在启用 real_ip_* 后已自动替换为真实客户端 IP。
验证是否生效:
- 写个
phpinfo();页面,看$_SERVER['REMOTE_ADDR']是否已是公网 IP - 若仍是代理 IP,说明
set_real_ip_from没覆盖到实际代理出口网段(比如云厂商 LB 用的是100.64.0.0/10,需补上) - 避免手写解析逻辑:
explode(',', $_SERVER['HTTP_X_FORWARDED_FOR'])[0]是危险且多余的
日志和 access_log 中记录真实 IP 的写法
别再用 $remote_addr 写日志。启用 realip 后,$remote_addr 已是真实 IP,可直接用;但更稳妥是显式使用 $realip_remote_addr(Nginx ≥1.11.0):
log_format main '$realip_remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';注意:$realip_remote_addr 在未匹配任何 set_real_ip_from 时会退化为 $remote_addr,所以它比硬写 $remote_addr 更健壮。
最易忽略的一点:set_real_ip_from 的 IP 段必须精确匹配你实际的上游代理出口地址,多一个 /32 少一个 /16 都会导致真实 IP 解析失败。上线前务必用 curl -H "X-Forwarded-For: 203.0.113.5" http://your-site/ 配合 nginx -t && nginx -s reload 验证。











