Y a-t-il un bon moyen de faire correspondre une adresse IPv6 à un sous-réseau IPv6 à l'aide de la notation CIDR?
Ce que je cherche, c'est l'équivalent IPv6 à ceci:
correspondant à une adresse IP à un masque CIDR dans PHP 5? A > p>
L'exemple indiqué ci-dessus ne peut pas être utilisé car une adresse IPv6 est de 128 bits de long, empêchant ainsi le décalage de gauche du bitwise de fonctionner correctement. Pouvez-vous penser à une autre manière? P>
Edit: Ajout de ma propre solution à la liste des réponses. P>
7 Réponses :
Puisque vous ne pouvez pas convertir les adresses IPv6 en Integer, vous devez utiliser des bits, comme celui-ci: De plus, si vous utilisez une base de données pour stocker IPS, il peut déjà avoir toutes les fonctions à Comparez-les. Par exemple, Postgres a un type INET et peut déterminer si IP est contenu dans la sous-réseau, comme celui-ci: p> 9.11. Fonctions d'adresse réseau et opérateurs dans PostgreSQL P> P>
Nice - Je n'ai jamais considéré comme des cordes binaires pour une raison quelconque.
"Vous ne pouvez pas convertir les adresses IPv6 en Integer". Je suppose que c'est parce qu'ils sont des 128 bits et les entiers sont limités à 32 ou 64 bits?
Je n'ai pas compris l'appel de déballage. Dans mon cas, il semble fonctionner mieux sans elle. Le masque net se termine souvent par 0 et ils sont enlevés. donc foreach (str_split ($ INET) comme $ char) code> semble être correct
J'ai créé ma propre solution, à l'aide du code suivant:
$subnet = inet_pton("2001:06b8::"); $mask = 32; $addr = inet_pton("2001:06b8:0000:0000:0000:0000:1428:07ab"); $match = iPv6CidrMatch($addr, $subnet, $mask); // TRUE
Si vos masques sont toujours divisibles par quatre (ce qui est assez courant dans IPv6). Vous pouvez utiliser:
function checkIPv6WithinRange($ipv6, $range) { list ($net, $mask) = preg_split("/\//", $range); if ($mask % 4) throw new NotImplementedException("Only masks divisible by 4 are supported"); $stripChars = (128-$mask)/4; $hexNet = bin2hex(inet_pton($net)); $reducedNet = substr($hexNet, 0, 0 - $stripChars); $hexIp = bin2hex(inet_pton($ipv6)); $reducedIp = substr($hexIp, 0, 0 - $stripChars); return $reducedIp === $reducedNet; }
J'ai beaucoup de masques qui ne sont pas divisibles par 4 - à la maison i>!
Simplification: substrateur ($ hexnet, 0, $ masque / 4). De cette façon ça marche sur ipv4 aussi :)
"Si vos masques sont toujours divisibles par quatre" peuvent être courants, mais c'est exactement le type de limitation arbitraire qui doit vous mordre dans les fesses. Ne recommanderait pas cette solution.
Fondamentalement http://www.phpclasses.org/browse/file/70429.html
Pour l'utiliser, appelez simplement P>
$cidr = new CIDR(); $cidr->match($ipv6, $ipv6_in_cidr);
Voici un exemple qui fonctionne en cochant une adresse IP sur une liste d'IPS ou de CIDR individuels, IPv4 et IPv6:
https://gist.github.com/lyQuix-owner/2620DA22D927C99D57555530AAB3279B p>
<?php // IP to check $ip_check = $_SERVER['REMOTE_ADDR']; // Array of allowed IPs and subnets, both IPv4 and IPv6 $ips_allowed = array( '192.30.252.0/22', '2620:112:3000::/44', '192.168.16.104' ); // Flag for IP match allowed list $allow = false; foreach($ips_allowed as $ip_allow) { // If IP has / means CIDR notation if(strpos($ip_allow, '/') === false) { // Check Single IP if(inet_pton($ip_check) == inet_pton($ip_allow)) { $allow = true; break; } } else { // Check IP range list($subnet, $bits) = explode('/', $ip_allow); // Convert subnet to binary string of $bits length $subnet = unpack('H*', inet_pton($subnet)); // Subnet in Hex foreach($subnet as $i => $h) $subnet[$i] = base_convert($h, 16, 2); // Array of Binary $subnet = substr(implode('', $subnet), 0, $bits); // Subnet in Binary, only network bits // Convert remote IP to binary string of $bits length $ip = unpack('H*', inet_pton($ip_check)); // IP in Hex foreach($ip as $i => $h) $ip[$i] = base_convert($h, 16, 2); // Array of Binary $ip = substr(implode('', $ip), 0, $bits); // IP in Binary, only network bits // Check network bits match if($subnet == $ip) { $allow = true; break; } } } if(!$allow) { die('IP not allowed'); }
php peut effectuer des opérations biteux sur les chaînes!