IP Matching With CIDR Notation In PHP

Sometimes you can’t find an answer, no matter how hard you Google. I consider myself lucky to have found this answer!

The Problem: You have a list of IP ranges in CIDR notation. You need to take visiting IPs and evaluate if they are within this list of allowed addresses. And, you need to do it in PHP.

The Answer: Load your CIDR list into an array and evaluate each visiting IP with the following function (found here)…

function ipfilter($ip) {
    $source = array("10.0.0.0/8",
        "192.168.1.1/32",
        "127.0.0.0/8");
    foreach ($source as $line) {
    

        // Get the base and the bits from the CIDR
        list($base, $bits) = explode('/', $line);
       
        // Now split it up into it's classes
        list($a, $b, $c, $d) = explode('.', $base);
       
        // Now do some bit shifting/switching to convert to ints
        $i    = ($a << 24) + ($b << 16) + ( $c << 8 ) + $d;
        $mask = $bits == 0 ? 0: (~0 << (32 - $bits));
       
        // Here's our lowest int
        $low = $i & $mask;
       
        // Here's our highest int
        $high = $i | (~$mask & 0xFFFFFFFF);
       
        // Now split the ip we're checking against up into classes
        list($a, $b, $c, $d) = explode('.', $ip);
       
        // Now convert the ip we're checking against to an int
        $check = ($a << 24) + ($b << 16) + ( $c << 8 ) + $d;
       
        // If the ip is within the range, including highest/lowest values,
        // then it's witin the CIDR range
        if ($check >= $low && $check <= $high) {
            return 1;
        }
    }
    return 0;

}

Is it efficient? I don’t know. Does it work? Yes it does. And thats more than I can say about other solutions to this problem that I found (here and elsewhere).

This entry was posted in News. Bookmark the permalink.

2 Responses to IP Matching With CIDR Notation In PHP

  1. Bill says:

    I wish I could claim it as my own, but the code and comments are both from the zend site. I posted this only to make it easier for people to find the solution. Glad it helped!

  2. Thanks for the excellent function, Bill! I also tried some functions from http://www.php.net; some of them I could tell wouldn’t always work, and some seemed like the would until I tested them. I guess when all else fails you just need to go back to the basics of converting bitmasks and IP addresses. I appreciate the commented code! You will find this code in Tera-WURFL 2.1.1 (TeraWurflWebservice.php) once I release it!

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>