PHP HTTP真实IP获取
·
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/8、192.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';
}
更多推荐


所有评论(0)