8
votes

7 Réponses :


16
votes

Puisque vous ne pouvez pas convertir les adresses IPv6 en Integer, vous devez utiliser des bits, comme celui-ci: xxx

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: xxx

9.11. Fonctions d'adresse réseau et opérateurs dans PostgreSQL


3 commentaires

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) semble être correct



4
votes

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


0 commentaires

1
votes

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;
}


3 commentaires

J'ai beaucoup de masques qui ne sont pas divisibles par 4 - à la maison !


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.



7
votes

Vous pouvez également utiliser iPuttils code> classe de Symfony / http-fondation Package:

IpUtils::checkIp6('2a01:8760:2:3001::1', '2a01:8760:2:3001::1/64')


0 commentaires

0
votes

Fondamentalement http://www.phpclasses.org/browse/file/70429.html

Pour l'utiliser, appelez simplement P>

$cidr = new CIDR();
$cidr->match($ipv6, $ipv6_in_cidr);


0 commentaires

3
votes

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');
}


2 commentaires

Cette réponse fait un peu plus que ce qui est demandé par le point de vue, mais est plein.


Aussi base_convert ne fonctionne pas pour ipv6 à cause de Ce et Ceci



2
votes

php peut effectuer des opérations biteux sur les chaînes!

  • IPv4 ou IPv6
  • pas de conversion de base
  • pas de cordes de bits ASCII
  • assez rapide xxx

0 commentaires