2

On one hand I have an IP like 123.3.2.3 and I would like to compare it with an array of allowed IPs like:

$allowedIps = ['123.*.*.*', '123.3.2.3', '123.3.2.3::1', '123.3.*.3']

In this case it should match all of the items.

Is there a simple way to do this without having to create a complex string comparison algorithm?

Raul Leaño Martinet
  • 2,035
  • 6
  • 28
  • 44

1 Answers1

1

If you don't intend to use wildcards as 123.3.2*.3, which would match any IP between 123.3.20.3 and 123.3.29.3, then the solution below would work fine.

Loop over the IPs in the array, and if there exists a wildcard in it, create two new IPs - one where the wildcard * is replaced by 0, the other replaced by 255. This is the lower and upper limit. Then you convert it to an integer, instead of an IP-string, using the ip2long() function. Do this both on the IP itself, and the value in the array as you loop them.

Then its only a matter of comparing them, that it is in fact between the upper and lower limit.

If there is no wildcard in the string, do a direct comparison.

$allowedIps = ['123.2.*.*', '123.3.2.3', '123.3.*.3'];
$IP = '123.3.1.3';
$match = 0;

foreach ($allowedIps as $allowed) {
    // If there is no wildcard, we check for the specific IP instead, and not a range
    if (strpos($allowed, "*") !== false) {
        $lowest = str_replace("*", "0", $allowed);
        $highest = str_replace("*", "255", $allowed);

        if (ip2long($IP) >= ip2long($lowest) && ip2long($IP) <= ip2long($highest)) {
            echo "$IP matched $allowed";
            $match = 1;
            break;
        }
    } elseif (ip2long($IP) === ip2long($allowed)) {
        echo "Matched ".$allowed;
        $match = 1;
        break;
    }
}

Probably wouldn't even need the condition to check if there are wildcards, as it wouldn't replace anything and both conditions in the subsequent if condition would be true.

Fair warning, I have not fully tested this, and there might be some obscure cases where the conditions might fail. You might be better off doing this outside of PHP as well.

Qirel
  • 25,449
  • 7
  • 45
  • 62