HTTP真实IP获取方法解析

多层代理环境下的IP获取策略
在存在CDN、负载均衡或反向代理的架构中,客户端真实IP可能存在于不同HTTP头中。常见优先级顺序为HTTP_CLIENT_IP > HTTP_X_FORWARDED_FOR > REMOTE_ADDR,需注意代理服务器可能会篡改这些头部。

典型代码实现要点:

$sources = [
    'HTTP_CLIENT_IP',
    'HTTP_X_FORWARDED_FOR', 
    'REMOTE_ADDR'
];

IP验证与处理规范

多IP代理链处理
X-Forwarded-For包含逗号分隔的IP链时,应取第一个非内网IP。需注意代理服务器可能追加伪造IP,典型处理方式:

if (strpos($candidate, ',') !== false) {
    $ips = array_map('trim', explode(',', $candidate));
    $candidate = array_reduce($ips, function($carry, $item) {
        return $carry ?: (filter_var($item, FILTER_VALIDATE_IP) ? $item : null);
    });
}

严格IP格式验证
使用PHP内置过滤器进行验证:

filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)

安全防护建议

  • 内网IP过滤:应排除10.0.0.0/8192.168.0.0/16等RFC私有地址段
  • 代理头可信度:仅信任配置过的代理服务器追加的头部
  • IP标准化存储:建议将IPv6转为完整格式,IPv4转为整型存储

补充验证逻辑示例:

function isValidPublicIp($ip) {
    return filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE) 
        || filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 | FILTER_FLAG_NO_PRIV_RANGE);
}

方法示例:

/**
 * 安全获取客户端真实IP
 * @return string 验证通过的IP或'unknown'
 */
function getRealIp() {
    $sources = [
        'HTTP_CLIENT_IP',
        'HTTP_X_FORWARDED_FOR',
        'REMOTE_ADDR'
    ];
    
    $ip = '';
    foreach ($sources as $source) {
        if (!empty($_SERVER[$source])) {
            $candidate = trim($_SERVER[$source]);
            
            // 处理多IP代理链(取第一个有效IP)
            if (strpos($candidate, ',') !== false) {
                $ips = explode(',', $candidate);
                $candidate = trim($ips[0]);
            }
            
            // 验证IP格式
            if (filter_var($candidate, FILTER_VALIDATE_IP)) {
                $ip = $candidate;
                break;
            }
        }
    }
    return $ip ?: 'unknown';
}

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐