PHP获取客户端真实IP穿透CDN与代理配置
时间:2026-11-14 07:12 作者:emer 分类: PHP
前言
网站接入 CDN 或 Nginx 反代后,PHP 用 $_SERVER['REMOTE_ADDR'] 拿到的是代理节点 IP,不是访客真实 IP,导致封禁、统计、风控全部失效。真实 IP 藏在代理转发的请求头里,需要按可信来源读取。本文讲解各代理头含义、安全读取真实 IP 的写法、防伪造校验,以及 CDN 场景注意事项。
操作步骤
1. 先看代理传了哪些头
<?php
print_r($_SERVER);
常见头:X-Forwarded-For、X-Real-IP、CF-Connecting-IP(Cloudflare)。
2. 标准读取 X-Forwarded-For
function getRealIp(){
$keys = ['HTTP_X_FORWARDED_FOR','HTTP_X_REAL_IP','HTTP_CF_CONNECTING_IP'];
foreach($keys as $k){
if(!empty($_SERVER[$k])){
// XFF 可能是逗号分隔链,取第一个
$ip = explode(',', $_SERVER[$k])[0];
return trim($ip);
}
}
return $_SERVER['REMOTE_ADDR'];
}
echo getRealIp();
3. Nginx 转发真实 IP 头
在反代 location 里加:
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
4. 只信任自有代理,防止伪造
function getRealIp(){
$proxyList = ['127.0.0.1','你的CDN/代理网段'];
if(in_array($_SERVER['REMOTE_ADDR'], $proxyList)){
return trim(explode(',',$_SERVER['HTTP_X_FORWARDED_FOR'])[0]);
}
return $_SERVER['REMOTE_ADDR'];
}
5. 校验 IP 格式
filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)
常见坑
- 直接信任 X-Forwarded-For 不校验来源,访客可伪造 IP。
- XFF 是逗号链,取成整串导致 IP 非法。
- CDN 更换后请求头名称变化,代码写死单一头失效。
- 多层代理 REMOTE_ADDR 永远是最前一跳,必须读头。
- IPv6 地址格式未处理,校验函数误判。
- 本地调试没有代理,读到的是内网 IP。
- 微信、支付回调场景不能依赖访客 IP,以业务令牌为准。
总结
真实 IP 读取原则:先确认请求来自可信代理,再从 X-Forwarded-For 取链首 IP,并用 filter_var 校验。Nginx 反代要主动转发 X-Real-IP 和 XFF。安全场景务必校验来源 IP,避免被伪造;统计场景可放宽但要说明数据口径。
遇到问题加QQ23979811 协助处理