frik Posted March 15, 2015 Share Posted March 15, 2015 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 More sharing options...
kicken Posted March 15, 2015 Share Posted March 15, 2015 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; } Link to comment https://forums.phpfreaks.com/topic/295231-how-to-match-ipv6-addresses/#findComment-1508087 Share on other sites More sharing options...
frik Posted March 15, 2015 Author Share Posted March 15, 2015 On 3/15/2015 at 4:27 AM, kicken said: 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. Link to comment https://forums.phpfreaks.com/topic/295231-how-to-match-ipv6-addresses/#findComment-1508092 Share on other sites More sharing options...
Recommended Posts
Archived
This topic is now archived and is closed to further replies.