如果 $_SERVER 不包含 IPv4 ip 怎么办?

Posted

技术标签:

【中文标题】如果 $_SERVER 不包含 IPv4 ip 怎么办?【英文标题】:What if the $_SERVER does not contain the IPv4 ip? 【发布时间】:2021-02-11 06:19:50 【问题描述】:

我正在尝试编写一个 php 脚本以使用此函数获取客户端的 IP 地址:

public function getIpAddress() 
    $ipAddress = '';
    if (! empty($_SERVER['HTTP_CLIENT_IP']) && $this->isValidIpAddress($_SERVER['HTTP_CLIENT_IP'])) 
        // check for shared ISP IP
        $ipAddress = $_SERVER['HTTP_CLIENT_IP'];
     else if (! empty($_SERVER['HTTP_X_FORWARDED_FOR']) && $this->isValidIpAddress($_SERVER['HTTP_CLIENT_IP'])) 
        // check for IPs passing through proxy servers
        // check if multiple IP addresses are set and take the first one
        $ipAddressList = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
        foreach ($ipAddressList as $ip) 
            if ($this->isValidIpAddress($ip)) 
                $ipAddress = $ip;
                break;
            
        
     else if (! empty($_SERVER['HTTP_X_FORWARDED']) && $this->isValidIpAddress($_SERVER['HTTP_X_FORWARDED'])) 
        $ipAddress = $_SERVER['HTTP_X_FORWARDED'];
     else if (! empty($_SERVER['HTTP_X_CLUSTER_CLIENT_IP']) && $this->isValidIpAddress($_SERVER['HTTP_X_CLUSTER_CLIENT_IP'])) 
        $ipAddress = $_SERVER['HTTP_X_CLUSTER_CLIENT_IP'];
     else if (! empty($_SERVER['HTTP_FORWARDED_FOR']) && $this->isValidIpAddress($_SERVER['HTTP_FORWARDED_FOR'])) 
        $ipAddress = $_SERVER['HTTP_FORWARDED_FOR'];
     else if (! empty($_SERVER['HTTP_FORWARDED']) && $this->isValidIpAddress($_SERVER['HTTP_FORWARDED'])) 
        $ipAddress = $_SERVER['HTTP_FORWARDED'];
     else if (! empty($_SERVER['REMOTE_ADDR']) && $this->isValidIpAddress($_SERVER['REMOTE_ADDR'])) 
        $ipAddress = $_SERVER['REMOTE_ADDR'];
    else
        $ipAddress = 'error';
    
    return $ipAddress;

我尝试了很多次,它正在工作。但我尝试连接到 ***,它检索到的是 IPv6 而不是 IPv4!

这可能是正常情况,但我需要获取该 PHP 脚本访问者的 IPv4。 我在谷歌上搜索了很多关于将 IPv6 转换为 IPv4 的信息,但我知道它无法转换。

但我注意到一些 IP 地理定位服务正在检索同一 *** 的 IPv4(在同一设备上)!例如:canyouseeme.org 和 api.ipify.org。

也就是说,即使无法将 IPv6 转换为 IPv4,即使访问者使用的是 IPv6,也可以实现一种方法来获取 IPv4!

我的问题:

如果这两个版本之间无法转换,这些 IP 地理定位服务是如何检索访问者的 IPv4 的? 如果他们没有将 IPv6 转换为 IPv4。因此,他们直接检索 IPv4 而不接触 IPv6。但是,如果 $_SERVER 不包含 IPv4,他们是如何做到的?

除此之外,我注意到当我访问whatismyipaddress.com 时,他们首先检索了 IPv6,然后它开始在 IPv4 字段旁边加载,然后他们检索了它!

注意:所有这些网站都检索到相同的 IPv4。

谢谢。

【问题讨论】:

他们可能使用某种仅限 IPv4 的网络服务器来检索您的 IPv4。 @tkausl 那么,购买仅支持 IPv4 的网络服务器会是解决方案吗? 假设客户端没有IPV4地址? 所有的http头都很容易被欺骗,所以不要依赖它们。 与其为未来而战,不如修复您的应用程序使其也适用于 IPv6 不是更好吗? 【参考方案1】:

只需从您的 DNS 名称中删除 AAAA 记录(或在您的 webservrr 中禁用 ipv6 - 这可能会导致延迟,因为浏览器应该更喜欢 ipv6),然后,没有 ipv4 的人无法再访问您的服务。正如@MagnusEriksson 所说:“与其为未来而战,不如修复您的应用程序以使其也适用于 IPv6 不是更好吗?”

另外,请注意,如果 ip 地址对您来说非常重要,那么 http 标头很容易被客户端(即不信任用户提供的数据)欺骗,或者代理服务器可能会提供 RFC1918 中定义的私有 ip .您应该只考虑/使用您知道服务器前面的受信任代理使用的标头 - 在所有其他情况下,您不能信任用户提供的标头。

【讨论】:

我的应用程序无法使用 IPv6。因为,我有一个“坏 IP”数据库,我将在其中搜索客户端的 IP。这些 IP 是第 4 版。该列表包含大约 1300 万行。 在此期间,网络服务器不支持 IPv6 (Hostgator)。但我正在使用 Cloudflare。【参考方案2】:

如果您使用的是 apache,您可能需要检查是否有任何 IPv6 Bindings 或 VirtualHosts。其他网络服务器也会有类似的设置

如果您无权访问网络服务器配置,您可以查看您的虚拟主机面板中是否有禁用 IPv6 的选项

此外,这可能是客户端控制的,即当您使用 *** 连接时,将为该网络接口(或隧道)启用 IPv6。在这种情况下,您不能强制访问者在其设备/路由器上禁用 IPv6,但您可以尝试在您的终端禁用它。不像 HTTPS Everywhere 只接受端口 443 或什么都不接受,我不认为 IP 地址处于只能接受 IPv6 而不能回退到 IPv4 的阶段,所以这个建议应该是安全的

【讨论】:

本站托管的网络服务器不支持 IPv6!但我使用 Cloudflare。会有影响吗?

以上是关于如果 $_SERVER 不包含 IPv4 ip 怎么办?的主要内容,如果未能解决你的问题,请参考以下文章

ubuntu18.04_server配置静态IPv4

在 Microsoft SQL Server 中存储 IP 地址

算法判断IP地址是不是合法的,包含IPv4和IPv6

算法判断IP地址是不是合法的,包含IPv4和IPv6

IPv4与IPv6数据报格式

IPv4数据报格式及其语义