在 PHP 中,获取访客的真实 IP 地址并不总是简单的,因为用户可能通过X_X服务器、CDN 或者负载均衡器访问网站。为了尽可能准确地获取访客的原始 IP,你需要检查多个 HTTP 头部信息(如 HTTP_X_FORWARDED_FOR 和 HTTP_CLIENT_IP),同时也要注意防止伪造。
下面是一个可靠的封装函数,用于获取访客的真实 IP 地址:
<?php
function get_visitor_ip() {
$ip = '';
// 检查X_X头信息
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
// 检查是否有客户端IP设置
$ip = $_SERVER['HTTP_CLIENT_IP'];
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
// 如果有多个IP,用逗号分隔,取第一个非未知IP
$ipList = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
foreach ($ipList as $proxyIp) {
$proxyIp = trim($proxyIp);
if (filter_var($proxyIp, FILTER_VALIDATE_IP)) {
$ip = $proxyIp;
break;
}
}
} elseif (!empty($_SERVER['REMOTE_ADDR'])) {
// 最后使用远程地址
$ip = $_SERVER['REMOTE_ADDR'];
}
// 防止伪造:如果最终得到的是空IP或局域网IP,返回 UNKNOWN
if (!$ip || !filter_var($ip, FILTER_VALIDATE_IP) || is_private_ip($ip)) {
return 'UNKNOWN';
}
return $ip;
}
/**
* 判断是否为私有IP(局域网IP)
*/
function is_private_ip($ip) {
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE)) {
return false;
}
return true;
}
// 示例调用
echo '访客IP是:' . get_visitor_ip();
📌 函数说明:
-
优先级顺序:
HTTP_CLIENT_IPHTTP_X_FORWARDED_FORREMOTE_ADDR
-
安全性处理:
- 对每个 IP 进行合法性验证(
filter_var(..., FILTER_VALIDATE_IP))。 - 跳过局域网 IP(如 192.168.x.x、10.x.x.x、172.16.x.x–172.31.x.x)。
- 如果所有方式都无法获取合法 IP,则返回
'UNKNOWN'。
- 对每个 IP 进行合法性验证(
-
注意事项:
HTTP_X_FORWARDED_FOR和HTTP_CLIENT_IP是可以被客户端伪造的,不能完全信任。- 如果你使用 CDN(如 Cloudflare),请根据 CDN 的文档从特定头部(如
HTTP_CF_CONNECTING_IP)中获取真实 IP。 - 在安全敏感场景(如登录日志、封禁 IP 等),建议结合数据库记录和行为分析进行判断。
✅ 示例输出:
访客IP是:192.0.2.1
如果你的应用部署在反向X_X或 CDN 后面,可以根据实际环境增加对以下头部的支持:
$_SERVER['HTTP_X_FORWARDED_FOR']
$_SERVER['HTTP_X_REAL_IP']
$_SERVER['HTTP_CF_CONNECTING_IP'] // Cloudflare
$_SERVER['HTTP_TRUE_CLIENT_IP'] // Cloudflare(启用时)
需要根据你的服务器架构做适当调整。
如有具体部署环境(如 Nginx + CDN),也可以提供,我可以帮你定制更精准的函数版本。
CDNK博客