
本文详解如何在 php 中准确获取客户端真实 ipv4 地址,避免误用 ipify 等外部 api 返回服务器自身 ip,并提供兼容 cdn(如 cloudflare)的健壮方案及 ipv4 强制格式化方法。
本文详解如何在 php 中准确获取客户端真实 ipv4 地址,避免误用 ipify 等外部 api 返回服务器自身 ip,并提供兼容 cdn(如 cloudflare)的健壮方案及 ipv4 强制格式化方法。
在 Web 开发中,一个常见误区是误将「获取公网 IP」等同于「获取用户 IP」。你当前使用的 https://api4.ipify.org 是一个返回当前发起请求的服务器出口 IP 的服务——当你的 PHP 脚本在服务器上执行时,它发出的 HTTP 请求自然来自服务器本身,因此得到的是你的网站服务器公网 IP,而非访问者的 IP。
要获取真实访客 IP,应直接依赖 PHP 的超全局变量 $_SERVER,但需注意:原始值可能受代理、CDN 或负载均衡器影响。以下是推荐的健壮处理流程:
✅ 推荐方案:多层校验 + IPv4 强制转换
<?php function getUserIPv4() {
$ip = '';
// 优先检查 Cloudflare 等可信 CDN 提供的头信息(需确保 CDN 已正确配置并信任该 Header)
if (isset($_SERVER['HTTP_CF_CONNECTING_IP']) && filter_var($_SERVER['HTTP_CF_CONNECTING_IP'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
$ip = $_SERVER['HTTP_CF_CONNECTING_IP'];
}
// 其次检查通用代理头(X-Forwarded-For),取最左侧第一个 IPv4 地址(防伪造,仅适用于可信内网环境)
elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$ips = array_map('trim', explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']));
foreach ($ips as $candidate) {
if (filter_var($candidate, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
$ip = $candidate;
break;
}
}
}
// 最终回退到 REMOTE_ADDR(最可靠,但可能为代理 IP)
if (empty($ip) && isset($_SERVER['REMOTE_ADDR'])) {
$ip = $_SERVER['REMOTE_ADDR'];
}
// 强制确保为 IPv4 格式(自动丢弃 IPv6,不修改服务器配置)
if ($ip && filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
return $ip;
}
return '0.0.0.0'; // 无效 IP 时的兜底值
}
$ipv4 = getUserIPv4();
echo "Visitor's IPv4 address is: " . htmlspecialchars($ipv4);
?>
⚠️ 重要注意事项
-
安全性前提:
HTTP_X_FORWARDED_FOR和HTTP_CF_CONNECTING_IP均可被客户端伪造。仅当你的应用部署在可信反向代理(如 Nginx 配置了set_real_ip_from)或已启用 Cloudflare 的“Authenticated Origin Pull”时,才可安全使用这些 Header。否则,请始终以$_SERVER['REMOTE_ADDR']为准,并在日志/风控中注明其可能为代理节点 IP。 -
IPv4 强制逻辑:
filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)不仅验证,也天然排除 IPv6;无需额外正则或inet_pton()转换。 -
不要依赖外部 API 获取用户 IP:
ipify、icanhazip.com等服务设计目标是返回调用方机器的出口 IP,本质是服务端行为,与客户端无关——这在获取用户 IP 场景下完全错误。
✅ 总结
获取用户真实 IPv4 地址的关键在于:信任链可控的请求头 + 严格 IPv4 校验 + 合理回退策略。跳过不必要的网络请求(如 ipify),既提升性能,又增强可靠性与安全性。对于绝大多数标准部署(含 Cloudflare),上述函数已兼顾兼容性与安全性,可直接集成至项目中。










