前言,最近 Cloudflare 的 IP 获取有些变化,导致获取用户的 IP 出现一些问题,经过测试记录一下
以下解释以 PHP 中的 $_SERVER 中的值为例
一般来说,在不使用反向代理的情况下,我们通常使用 REMOTE_ADDR 获取客户端的 IP
REMOTE_ADDR
但是在使用了反向代理之后,我们使用 HTTP_X_FORWARDED_FOR,因为 REMOTE_ADDR 已经是反向代理服务器的 IP
HTTP_X_FORWARDED_FOR
但是众所周知 HTTP_X_FORWARDED_FOR 值是可以伪造的,而它可以以逗号为连接的多个值,所以很不安全
这时候,在使用 Cloudflare 的情况下,Cloudflare 设置 HTTP_CF_CONNECTING_IP 获取 IP
HTTP_CF_CONNECTING_IP
坑来了,注意以下测试数据
细心的管理员会发现,有些用户的 IP 通过 HTTP_X_FORWARDED_FOR 和 HTTP_CF_CONNECTING_IP 获取均为内网 IP ,例如:251.120.126.7
经过推测,应该是电信运营商为用户分配了 IPV6 地址,但同时也分配了 IPV4 地址,只不过为了节省 IP 资源,IPV4 设置为内网 IP ,这时候 HTTP_CF_CONNECTING_IP 值就准确了
怎么办呢?
这个时候 Cloudfalre 请求中设置的 HTTP_CF_CONNECTING_IPV6 就要登场了,因为在以上 HTTP_CF_CONNECTING_IP 为内网地址的情况下,HTTP_CF_CONNECTING_IPV6 会显示真实的 IPV6 地址
HTTP_CF_CONNECTING_IPV6
所以,如果你有相关业务需求,你可以编写一个函数,以下以 Laravel 框架公共函数来处理。注意,这是在使用 Cloudflare 的情况下,其他 CDN 服务商需要参考对应文档
function getClientIp() { $request = request(); // 尝试获取IPv4地址 $ipv4 = $request->header('CF-Connecting-IP'); if ($ipv4 && filter_var($ipv4, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) { return $ipv4; } // 如果IPv4无效,尝试获取IPv6地址 $ipv6 = $request->header('CF-Connecting-IPv6'); if ($ipv6 && filter_var($ipv6, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) { return $ipv6; } // 如果Cloudflare的头部都无效,尝试使用X-Forwarded-For $forwardedIp = $request->header('X-Forwarded-For'); if ($forwardedIp) { $ips = explode(',', $forwardedIp); $firstIp = trim($ips[0]); if (filter_var($firstIp, FILTER_VALIDATE_IP)) { return $firstIp; } } // 最后,使用Laravel的getClientIp方法 return $request->getClientIp(); }
最后感谢 Cloudflare ,致敬!
标签:Cloudlfare,HTTP,IP,CF,CONNECTING,IPV4,IPV6,Cloudflare From: https://www.cnblogs.com/kavo/p/18489901