Jump to content

How to match IPv6 addresses?


frik

Recommended Posts

Hello,

 

In my personal PHP application, I like to identify visitors to my website by checking the IP range

that their IP address falls into. This is easy enough for IPv4 when I have the CIDR.

For IPv6 however it is another matter entirely, because at present I don't know

how to match an IPv6 address. As a result I am using the cumbersome substr matching

approach, which does not work for many addresses.

 

For example, consider 2620:149:f01:2b0:99ad:f010:61c1:63c5.

The CIDR is 2620:149::/36. The 0 nybble in the 3rd 32-bit word is implied most of the time

and this breaks the substr approach.

 

Surely there is by now a simple way to do this.

Can someone tell me the best solution that exists at present?

 

Thanks.

 

Link to comment
https://forums.phpfreaks.com/topic/295231-how-to-match-ipv6-addresses/
Share on other sites

You'll need to use GMP to store the addresses and compare against a given prefix. If your PHP build supports IPv6, you can use inet_pton to convert the human-readable address into a binary number. If you do not have IPv6 support, you will have to find or create your own parser for IPv6 addresses.

 

For example:

$address = '2620:149:f01:2b0:99ad:f010:61c1:63c5';
$network = '2620:149::/36';

$address = inet_pton($address);
$address = gmp_init(bin2hex($address), 16);

if (false !== $pos=strpos($network, '/')){
    $prefix = substr($network, 0, $pos);
    $bitlength = substr($network, $pos+1);
    $network = inet_pton($prefix);
    $network = gmp_init(bin2hex($network), 16);

    $mask = str_repeat('1', $bitlength).str_repeat('0', 128-$bitlength);
    $mask = gmp_init($mask, 2);
}
else {
    $network = inet_pton($prefix);
    $network = gmp_init(bin2hex($network), 16);

    $mask = str_repeat('1', 128);
    $mask = gmp_init($mask, 2);
}

$masked_address = gmp_and($address, $mask);
$masked_network = gmp_and($network, $mask);
if (gmp_cmp($masked_address, $masked_network) === 0){
    echo 'address is within the network.'.PHP_EOL;
}
else {
    echo 'address is not within the network.'.PHP_EOL;
}

You'll need to use GMP to store the addresses and compare against a given prefix. If your PHP build supports IPv6, you can use inet_pton to convert the human-readable address into a binary number. If you do not have IPv6 support, you will have to find or create your own parser for IPv6 addresses.

 

 

 

OK, that helps. Thanks.

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.