Gestion des plages d'IP en PHP/MySQL

Publié le mercredi 5 juillet 2023 à 18:59

J'ai eu récemment à trouver comment restreindre l'accès à un service en ligne à certaines plages d'IP. Voici la solution qui a répondu à mes besoins.

J'ai récemment du autoriser l'accès à un service en ligne à seulement quelques plages d'IP.

Premièrement, voyons comment calculer la première et la dernière adresse IP d'une plage (bloc CIDR) avec sa base et son masque :

$range = ['127.0.0.1', 8];
function rangeBegin($range) {
        return $range[0];
}
function rangeEnd($range) {
        return long2ip(ip2long($range[0]) | ((1 << (32 - $range[1])) - 1));
}

Maintenant comment vérifier si une IP est présente dans une plage (bloc CIDR) :

$ip = '127.0.0.1';
$range = ['127.0.0.1', 8];
function ipInRange($ip, $range) {
        if (ip2long($range[0]) <= ip2long($ip) && ip2long($ip) <= (ip2long($range[0]) | ((1 << (32 - $range[1])) - 1))) {
                return true;
        }
        return false;
}

En premier bonus, comment récupérer les plages d'IP d'amazon :

function fetchAmazonRange() {
        //Init array
        $amazonRanges = [];

        $ctx = stream_context_create(
                [
                        'http' => [
                                'method' => 'GET',
                                'max_redirects' => 0,
                                'timeout' => 5,
                                'ignore_errors' => false,
                                'header' => [
                                        'Connection: close',
                                        'Accept: application/json'
                                ]
                        ]
                ]
        ];

        //Fetch json
        if (($json = file_get_contents('https://ip-ranges.amazonaws.com/ip-ranges.json', false, $ctx)) === false) {
                return null;
        }

        //Decode it
        if (($json = json_decode($json)) === null || empty($json->prefixes)) {
                return false;
        }

        //Deal with prefixes
        foreach($json->prefixes as $range) {
                //Skip ipv6 and invalid ranges
                if (empty($range->ip_prefix)||!preg_match('/^([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\/([0-9]+)$/', $range->ip_prefix, $matche
s)) {
                        continue;
                }
                //Remove whole match
                array_shift($matches);
                //Add ip and mask
                $amazonRanges[] = $matches;
        }

        //Send back result
        return $amazonRanges;
}

Urls pour les plages d'IP de Microsoft Azure :