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:
- If the conversion is not possible between these two versions, how did these IP geolocation services retrieved the IPv4 of the visitor?
- If they are not converting the IPv6 into IPv4. So, they are retrieving the IPv4 directly without touching the IPv6. But, how did they do that if the $_SERVER does not contain an IPv4?
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.
2
Answers
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.
if you are using apache, you may want to check if there are any IPv6 Bindings or VirtualHosts. there will be similar settings for other web servers
if you don’t have access to the web server config, you can see if there’s an option to disable IPv6 in your webhost panel
also, this could be client-controlled, i.e. when you connect using a VPN then IPv6 is enabled for that network interface (or tunnel). in which case you cannot force the visitor to disable IPv6 on their device / router, but you could try to disable it on your end. unlike HTTPS Everywhere which only accepts port 443 or nothing, I don’t think IP addresses are at the stage where it is only possible to accept IPv6 with no fallback to IPv4, so this recommendation should be safe