PHP获取真实IP地址的常用方法对比

Luna
Luna
发布时间:2026-10-13 | 1人浏览过
原创

本文将介绍在PHP环境中如何获取客户端的真实IP地址,涵盖从基础的远程地址读取到处理反向代理和CDN场景的高级逻辑,并分析各方法的可靠性与潜在的安全隐患。

核心原理与准备

获取IP的核心在于解析HTTP请求头中的特定变量。不同的网络环境(直连、Nginx代理、负载均衡器、CDN)会设置不同的Header字段。通常优先级为:X-Forwarded-For > HTTP_CLIENT_IP > REMOTE_ADDR。需要注意的是,这些值均可被客户端伪造,因此在安全敏感场景下应结合白名单或信任的反向代理IP进行过滤。

常见实现方法详解

第1步:直接获取远程连接IP

目的: 获取直接与服务器建立TCP连接的IP地址。
操作: 使用 $_SERVER['REMOTE_ADDR']。
适用场景: 无代理服务器的直连环境。

$ip = $_SERVER["REMOTE_ADDR"];
echo $ip;

这是最基础的方法,但无法识别代理后的真实用户IP。

第2步:简单判断代理IP

目的: 优先尝试获取 X-Forwarded-For,若为空则回退到 REMOTE_ADDR。
操作: 检查 HTTP_VIA 或直接判断 X-Forwarded-For。

$user_IP = ($_SERVER["HTTP_VIA"]) ? $_SERVER["HTTP_X_FORWARDED_FOR"] : $_SERVER["REMOTE_ADDR"];
$user_IP = ($user_IP) ? $user_IP : $_SERVER["REMOTE_ADDR"];
echo $user_IP;

此方法比第一种更灵活,但仍存在逻辑漏洞,未处理多个逗号分隔的IP列表。

第3步:完整解析IP链(推荐用于通用场景)

目的: 正确解析 X-Forwarded-For 中的第一个可信IP,并过滤内网IP。
操作: 依次检查 HTTP_CLIENT_IP、HTTP_X_FORWARDED_FOR,对IP列表进行拆分和内网过滤。

function getRealIp()
{
  $ip=false;
  if(!empty($_SERVER["HTTP_CLIENT_IP"])){
    $ip = $_SERVER["HTTP_CLIENT_IP"];
  }
  if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
    // 注意:建议使用 explode(",", ...) 而非 ", ",视服务器配置而定
    $ips = explode (",", $_SERVER['HTTP_X_FORWARDED_FOR']);
    if ($ip) { array_unshift($ips, $ip); $ip = FALSE; }
    for ($i = 0; $i < count($ips); $i++) {
      // 过滤私有IP段:10.x.x.x, 172.16.x.x-172.31.x.x, 192.168.x.x
      if (!preg_match("/^(10|172\.1[6-9]|172\.2[0-9]|172\.3[0-1]|192\.168).*/, $ips[$i])) {
        $ip = $ips[$i];
        break;
      }
    }
  }
  return ($ip ? $ip : $_SERVER['REMOTE_ADDR']);
}
echo getRealIp();

注意: 原文使用了已废弃的 eregi 函数,建议替换为 preg_match 以兼容现代PHP版本。

第4步:多重 getenv 兼容写法

目的: 兼容部分旧版Apache或配置环境下 $_SERVER 缺失的情况,使用 getenv() 作为备选。
操作: 按顺序检查 HTTP_X_FORWARDED_FOR、HTTP_CLIENT_IP 和 REMOTE_ADDR。

if ($HTTP_SERVER_VARS["HTTP_X_FORWARDED_FOR"]){
  $ip = $HTTP_SERVER_VARS["HTTP_X_FORWARDED_FOR"];
}elseif ($HTTP_SERVER_VARS["HTTP_CLIENT_IP"]){
  $ip = $HTTP_SERVER_VARS["HTTP_CLIENT_IP"];
}else{
  $ip = $_SERVER['REMOTE_ADDR']; // 修正引用方式,避免歧义
}
echo $ip;

该写法较为冗长,且依赖全局变量 $HTTP_SERVER_VARS,在现代PHP中推荐使用超全局数组 $_SERVER。

第5步:简化条件分支

目的: 使用简洁的 if-elseif 结构获取IP。
操作: 优先 HTTP_CLIENT_IP,其次 HTTP_X_FORWARDED_FOR,最后 REMOTE_ADDR。

$onlineip = '';
if(getenv('HTTP_CLIENT_IP')) {
  $onlineip = getenv('HTTP_CLIENT_IP');
} elseif(getenv('HTTP_X_FORWARDED_FOR')) {
  $onlineip = getenv('HTTP_X_FORWARDED_FOR');
} elseif(getenv('REMOTE_ADDR')) {
  $onlineip = getenv('REMOTE_ADDR');
} else {
  $onlineip = $_SERVER['REMOTE_ADDR'];
}
echo $onlineip;

第6步:字符串输出封装

目的: 将获取逻辑直接嵌入页面输出流程。
操作: 定义变量后直接打印。

print "您的IP地址是:";
$cip = "Unknown";
if(!empty($_SERVER["HTTP_CLIENT_IP"])){
 $cip = $_SERVER["HTTP_CLIENT_IP"];
}elseif(!empty($_SERVER["HTTP_X_FORWARDED_FOR"])){
 $cip = $_SERVER["HTTP_X_FORWARDED_FOR"];
}elseif(!empty($_SERVER["REMOTE_ADDR"])){
 $cip = $_SERVER["REMOTE_ADDR"];
}
print $cip;

完成判断与安全提醒

判断标准: 脚本执行后能正确返回格式合法的IPv4或IPv6地址。
风险提示: X-Forwarded-For 等Header极易伪造。如果应用于高频交易或强安全认证,必须配置信任的代理IP列表(Trust Proxy List),仅信任来自可信网关的头部信息。否则,攻击者可轻易伪造来源IP进行DDoS伪装或绕过频率限制。

简要总结

PHP获取IP没有绝对完美的单行代码,需根据部署架构(是否经过Nginx/LVS/Cloudflare等)选择。一般业务推荐使用第3步的逻辑,并注意正则表达式的兼容性。以上就是PHP获取访问者IP地址方法的详细内容,更多关于PHP网络编程的资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表