Jump to content

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.

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • 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.