phpipip-geolocation

What if the $_SERVER does not contain the IPv4 ip?


I am trying to code a PHP script for getting the client's IP address using this function:

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;
}

I tried it many times and it's working. But I tried to connect to a VPN and it retrieved IPv6 instead of IPv4!

This could be a normal situation but I need to get the IPv4 of the visitor of that PHP script. I googled a lot about converting IPv6 to IPv4 and I know that it cannot be converted.

But I notices some IP geolocation services are retrieving IPv4 for the same VPN (on the same device)! For example: canyouseeme.org and api.ipify.org.

That's mean that even if the IPv6 cannot be converted into IPv4, there's a method can be implemented to get IPv4 even if the visitor is using IPv6!

My questions:

In additional to that, I noticed that when I visited whatismyipaddress.com, they retrieved the IPv6 first then it start loading beside the IPv4 field then they retrieved it!

Note: All these sites has retrieved the same IPv4.

Thanks.


Solution

  • Just drop the AAAA record from your DNS name (or disable ipv6 in your webservrr - this might introduce delays as browsers are supposed to prefer ipv6), then, however, people w/o ipv4 cannot access your service any more. As @MagnusEriksson said: "Instead of fighting the future, wouldn't it be better to fix your application so it works with IPv6 as well?"

    Also, please be aware, if the ip address is so important for you, that http headers can be easily spoofed by clients (i.e., don't trust user provided data) or proxy servers might provide private ips as defined in RFC1918. You should only consider/use the headers you know a trusted proxy infront of your server uses - in all other cases you cannot trust the user provided headers.