PHP获取客户端真实IP穿透CDN与代理配置 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)

常见坑

  1. 直接信任 X-Forwarded-For 不校验来源,访客可伪造 IP。
  2. XFF 是逗号链,取成整串导致 IP 非法。
  3. CDN 更换后请求头名称变化,代码写死单一头失效。
  4. 多层代理 REMOTE_ADDR 永远是最前一跳,必须读头。
  5. IPv6 地址格式未处理,校验函数误判。
  6. 本地调试没有代理,读到的是内网 IP。
  7. 微信、支付回调场景不能依赖访客 IP,以业务令牌为准。

总结

真实 IP 读取原则:先确认请求来自可信代理,再从 X-Forwarded-For 取链首 IP,并用 filter_var 校验。Nginx 反代要主动转发 X-Real-IP 和 XFF。安全场景务必校验来源 IP,避免被伪造;统计场景可放宽但要说明数据口径。

遇到问题加QQ23979811 协助处理


emer 发布于  2026-11-14 07:12 
'); })();