PHP中如何可靠的获取访客IP地址,封装一个函数?

在 PHP 中获取访客 IP 地址看似简单,但由于用户可能通过、CDN 或负载均衡器访问网站,直接使用 $_SERVER['REMOTE_ADDR'] 并不总是准确。因此,需要综合多个 HTTP 头信息来更可靠地判断真实客户端 IP。

以下是一个可靠的封装函数,用于获取访客的真实 IP 地址:

<?php

function get_client_ip() {
    // 优先级顺序:从最可信到最不可信
    $ip_keys = [
        'HTTP_CLIENT_IP',           // 客户端IP(较少使用)
        'HTTP_X_FORWARDED_FOR',     // 经过的IP列表
        'HTTP_X_FORWARDED',         // 类似上一个
        'HTTP_X_CLUSTER_CLIENT_IP', // 负载均衡集群中的客户端IP
        'HTTP_FORWARDED_FOR',       // 旧式头
        'HTTP_FORWARDED',           // 同上
        'HTTP_CF_CONNECTING_IP',    // Cloudflare CDN
        'HTTP_TRUE_CLIENT_IP',      // 部分CDN(如阿里云)
        'REMOTE_ADDR'               // 最后兜底:直接连接的IP
    ];

    foreach ($ip_keys as $key) {
        if (!isset($_SERVER[$key]) || empty($_SERVER[$key])) {
            continue;
        }

        // 获取IP字符串
        $ip_list = explode(',', $_SERVER[$key]);

        // 遍历IP列表,从左到右取第一个合法公网IP(排除私有IP和保留IP)
        foreach ($ip_list as $ip) {
            $ip = trim($ip);

            // 过滤私有/保留IP地址
            if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RESv4_RANGE)) {
                return $ip;
            }
        }
    }

    // 兜底返回本地地址(理论上不会走到这里)
    return '127.0.0.1';
}

// 使用示例:
$client_ip = get_client_ip();
echo "访客IP: " . $client_ip;

🔍 函数说明

头字段 说明
HTTP_CLIENT_IP 某些设置的客户端IP
HTTP_X_FORWARDED_FOR 常见/CDN 添加的原始IP列表
HTTP_CF_CONNECTING_IP Cloudflare 特有的头
REMOTE_ADDR 直接连接的服务器端看到的IP

⚠️ 注意:X-Forwarded-For 可被伪造,仅当你的应用部署在可信后方时才可信任。


✅ 安全建议

  1. 不要盲目信任所有头信息
    攻击者可以伪造 X-Forwarded-For 等头。如果你的应用暴露在公网,应只信任来自可信或 CDN 的头。

  2. 结合实际架构过滤
    如果你使用了 Nginx + PHP-FPM,并且 Nginx 已经设置了可信,可以在 Nginx 中统一设置头,PHP 只读取特定头。

    示例 Nginx 配置:

    location ~ .php$ {
        include fastcgi_params;
        fastcgi_param HTTP_X_FORWARDED_FOR $proxy_add_x_forwarded_for;
        fastcgi_param REMOTE_ADDR $proxy_add_x_forwarded_for;
        fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
    }
  3. 记录日志时建议同时记录所有来源IP,便于排查问题:

    $log_data = [
        'real_ip' => get_client_ip(),
        'remote_addr' => $_SERVER['REMOTE_ADDR'] ?? '',
        'x_forwarded_for' => $_SERVER['HTTP_X_FORWARDED_FOR'] ?? '',
    ];

🧪 测试示例

你可以用 curl 模拟请求测试:

curl -H "X-Forwarded-For: 1.2.3.4, 5.6.7.8" http://yoursite.com/test.php

函数会尝试从 X-Forwarded-For 中提取第一个合法公网 IP。


✅ 总结

这个函数通过:

  • 多个头部兼容性支持;
  • 排除私有/保留IP;
  • 返回最可能真实的客户端IP;

是目前在通用场景下较为可靠的获取访客 IP 的方式。

💡 提示:在高安全要求场景中,建议结合防火墙、WAF 和日志分析系统共同识别真实用户 IP。

未经允许不得转载:云计算HECS » PHP中如何可靠的获取访客IP地址,封装一个函数?