Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

An optimized method to compare IP addresses with wildcards in PHP?

Anyone know of an effective and secure method to see if this input:

$_SERVER['REMOTE_ADDR']

matches against something similar to this array of inconsistent filters (note that 200.100.*.* could be expressed as just 200.100.*) with wildcards indicated by *'s:

array(
  '192.168.1.*',
  '192.168.2.1*',
  '10.0.0.*',
  '200.100.*.*',
  '300.200.*',
)

Update

Thoughts?

foreach($instanceSettings['accessControl']['allowedIpV4Addresses'] as $ipV4Address) {
    echo 'Now checking against '.$ipV4Address.'.';

    // Compare each octet
    $ipV4AddressOctets = String::explode('.', $ipV4Address);
    $remoteIpV4AddressOctets = String::explode('.', $_SERVER['REMOTE_ADDR']);
    $remoteIpV4AddressIsAllowed = true;
    for($i = 0; $i < Arr::size($ipV4AddressOctets); $i++) {
        echo 'Comparing '.$ipV4AddressOctets[$i].' against '.$remoteIpV4AddressOctets[$i].'.';
        if($ipV4AddressOctets[$i] != $remoteIpV4AddressOctets[$i] && $ipV4AddressOctets[$i] != '*') {
            echo 'No match.';
            $remoteIpV4AddressIsAllowed = false;
            break;
        }
    }

    // Get out of the foreach if we've found a match
    if($remoteIpV4AddressIsAllowed) {
        break;
    }
}
like image 522
Kirk Ouimet Avatar asked Sep 30 '11 15:09

Kirk Ouimet


2 Answers

I haven't bench-marked this, but I would opt to use the method that networking hardware/software uses...

Replace any * with 0 and 255. Convert the IPs to integers

So if 255.255.255.* becomes 255.255.255.0 and 255.255.255.255 Then do ip2long function on these two ips.

Then you can convert the given ip into long ip. for example 255.255.50.51 into long ip.

Then you can compare whether the long ip for this given ip is between the converted long ips in the blacklist. If it is then it is not allowed else it is.

$ips = array("ip1", "ip2");
foreach($ips as $ip){
 $ip1 = str_replace("*", "0", $ip);
 $ip2 = str_replace("*", "255", $ip);

 $ip1 = ip2long($ip1);
 $ip2 = ip2long($ip2);
 $givenip = $_GET["ip"];
 $givenip = ip2long($givenip);

 if($givenip >= $ip1 && $ip <= $givenip){
   echo "blacklist ip hit between {$ip1} and {$ip2} on {$ip}";
 }
}
like image 157
Anush Avatar answered Oct 07 '22 22:10

Anush


Remove the asterisks and just do:

$ips = array('192.168.1.', '10.0.0.');

foreach ($ips as $ip) {
    if (strpos($_SERVER['REMOTE_ADDR'], $ip) === 0) {
        // match
    }
}
like image 38
webbiedave Avatar answered Oct 07 '22 22:10

webbiedave