简体   繁体   中英

check if an ip matches any ip contained in an ip list using php

in array $white I have an ip list like this (about 10000-12000 ips)

74.125.244.0/22
207.126.144.0/20
77.238.189. 
212.211.149.128/26
194.25.134.8 
194.25.134.9 
194.25.134.12       
174.2.114.12-174.2.115.255
153.2.242.243
153.2.244.12 
153.2.244.50 
153.2.244.63 
153.2.246.30 
153.2.246.31 
153.2.246.35 
153.2.247.30 
153.2.247.31 
153.2.247.32      

So, the ip list in array $white can contain ip(s) in these three format

153.2.247.32 (simple ip address)
207.126.144.0/20 ( CIDR notation )
174.2.114.12-174.2.115.255 ( Hyphenated ranges )

My goal is to check if ips listed in another array, $ips (about 1000-2000 ips), are present in the $white list.

The format in the $ips list is only simple ip address like

207.126.144.0
207.126.141.2
201.126.144.5

I am doing this

foreach ($ips as $check) {
if (in_array($check,$white)){
echo "Ip $check exists";
}
}

However it's only good to check simple ip addresses, but I cannot check if the ips listed in $ips are contained in the Hyphenated ranges and CIDR ranges of $white.

I found a solution using ip_in_range.php https://github.com/irazasyed/php-ip-range/blob/master/ip_in_range.php

foreach ($ips as $check) {
    if (in_array($check,$white))
    {
    echo "Ip $check exists";
    }
    else
    {
    foreach( $white as $checkrange )
    {       
if (substr_count($checkrange, '/')>=1 or substr_count($checkrange, '-')>=1 )
{ 
    if (ip_in_range($check, $checkrange)) 
{ 
    echo "Ip $check exists"; 
    break;
}
}

}
}
}

But it's very slow, because $white and $ips are huge lists. Does exist a faster and more efficient solution?

Pre-expand all the whitelist ranges into one giant list of singular IP addresses. For example, given:

1.2.3.4
2.3.4.5
3.4.5.6-3.4.5.10

You'd process the list once to generate this list:

1.2.3.4
2.3.4.5
3.4.5.6
3.4.5.7
3.4.5.8
3.4.5.9
3.4.5.10

Then, store that list in a key/value cache. Could be something as simple as a native PHP associative array sitting in memory, or something more robust like a Redis database. Then you've got a simple equivalency check for inclusion. Implemented correctly (eg, via array_key_exists() instead of in_array() ), you'll get O(1) performance for an IP lookup, regardless of the size of the whitelist. It can't get faster.

Instead of doing all the range processing over and over again on every single IP check, you're doing it only once when the whitelist changes. You're basically giving up memory to gain CPU.

You can try with preg_grep :

foreach ($ips as $check){

    if(preg_grep("/$check/i",$white))
    {
        echo $input." whitelisted";
    }else{
        echo $input." blacklisted";
    }
{

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM