2009-02-27 42 views
48

Tôi đang tìm phương pháp nhanh/đơn giản để kết hợp IP IP rải rác IP4 cho trước với mặt nạ chú thích CIDR.Kết hợp IP với mặt nạ CIDR trong PHP 5?

Tôi có một loạt các địa chỉ IP cần xem liệu chúng có khớp với một dải IP hay không.

dụ:

$ips = array('10.2.1.100', '10.2.1.101', '10.5.1.100', '1.2.3.4'); 

foreach ($ips as $IP) { 
    if (cidr_match($IP, '10.2.0.0/16') == true) { 
     print "you're in the 10.2 subnet\n"; 
    } 
} 

sẽ cidr_match() trông như thế nào?

Nó không thực sự đơn giản, nhưng nhanh chóng sẽ tốt. Bất cứ thứ gì chỉ sử dụng các hàm dựng sẵn/phổ biến là tiền thưởng (vì tôi có khả năng để một người chỉ cho tôi một cái gì đó trong quả lê làm điều này, nhưng tôi không thể phụ thuộc vào lê hoặc gói đó đang được cài đặt ở đâu mã của tôi đã triển khai).

Trả lời

64

Nếu chỉ sử dụng IPv4:

  • sử dụng ip2long() để chuyển đổi IP và phạm vi subnet thành số nguyên dài
  • chuyển đổi/xx thành một subnet mask
  • làm một phép toán 'và' (ví dụ: ip & mask) và kiểm tra xem đó là kết quả = subnet '

một cái gì đó như thế này nên làm việc:

function cidr_match($ip, $range) 
{ 
    list ($subnet, $bits) = explode('/', $range); 
    $ip = ip2long($ip); 
    $subnet = ip2long($subnet); 
    $mask = -1 << (32 - $bits); 
    $subnet &= $mask; # nb: in case the supplied subnet wasn't correctly aligned 
    return ($ip & $mask) == $subnet; 
} 
+0

có lẽ nếu bạn đăng phiên bản C# của mình, chúng tôi có thể tìm ra lý do tại sao? – Alnitak

+0

(mã PHP ở trên _does_ hoạt động cho ví dụ bạn đã cung cấp) – Alnitak

+1

Lưu ý rằng tính năng mặt nạ sẽ không hoạt động trên máy 64 bit. Bạn sẽ cần phải sử dụng một cái gì đó như '$ mask = (-1 << (32 - $ bit)) & ip2long ('255.255.255.255');' Không phải là cách sạch nhất, nhưng đơn giản. –

1
function cidr_match($ipStr, $cidrStr) { 
    $ip = ip2long($ipStr); 
    $cidrArr = split('/',$cidrStr); 
    $maskIP = ip2long($cidrArr[0]); 
    $maskBits = 32 - $cidrArr[1]; 
    return (($ip>>$maskBits) == ($maskIP>>$maskBits)); 
} 
+2

này sẽ không hoạt động trên các hệ thống 32-bit: trận đấu (1.2.3.4, 0.0.0.0/0) trả về false, nên trở về đúng –

0

Tôi muốn bạn xem vài dòng của mình. Các ví dụ mà mọi người đề xuất trước tôi dường như không hoạt động. Một lý do là, theo như tôi hiểu nó, là các bit mặt nạ CIDR là các số nhị phân, do đó, sự dịch chuyển bit phải được thực hiện trên một số nhị phân. Tôi đã thử chuyển đổi IP dài thành mã nhị phân, nhưng chạy vào giới hạn số nhị phân tối đa. OK, ở đây vài dòng của tôi ... Tôi đang chờ nhận xét của bạn.

function cidr_match($ipStr, $cidrStr) { 

$ipStr = explode('.', $ipStr); 
foreach ($ipStr as $key => $val) { 
    $ipStr[$key] = str_pad(decbin($val), 8, '0', STR_PAD_LEFT); 
    } 
$ip = ''; 
foreach ($ipStr as $binval) { 
    $ip = $ip . $binval; 
    } 

$cidrArr = explode('/',$cidrStr); 

$maskIP = explode('.', $cidrArr[0]); 
foreach ($maskIP as $key => $val) { 
    $maskIP[$key] = str_pad(decbin($val), 8, '0', STR_PAD_LEFT); 
    } 
$maskIP = ''; 
foreach ($ipStr as $binval) { 
    $maskIP = $maskIP . $binval; 
    } 
$maskBits = 32 - $cidrArr[1]; 
return (($ip>>$maskBits) == ($maskIP>>$maskBits)); 
} 
3

Một số chức năng thay đổi:

  • chia tay với nổ

function cidr_match($ip, $range) 
{ 
    list ($subnet, $bits) = explode('/', $range); 
    $ip = ip2long($ip); 
    $subnet = ip2long($subnet); 
    $mask = -1 << (32 - $bits); 
    $subnet &= $mask; 
    return ($ip & $mask) == $subnet; 
} 
+0

Dưới đây là một thực hiện bổ sung để kiểm tra chống lại IP CloudFlare của ví dụ: [code] $ ip \t \t = \t $ _SERVER ["REMOTE_ADDR"]; $ c1 \t \t = \t cidr_match ($ ip, '204.93.240.0/24'); $ c2 \t \t = \t cidr_match ($ ip, '204.93.177.0/24'); $ c3 \t \t = \t vv .. $ cTotal \t = \t vòng ($ c1 + $ c2 + $ c3 + ...); nếu ($ cTotal <1) die(); [/ code] –

3

kỹ thuật của tôi sử dụng chút để phù hợp chút sử dụng subnet và mặt nạ.

function cidr_match($ip, $range){ 
    list ($subnet, $bits) = explode('/', $range); 
    $ip = substr(IP2bin($ip),0,$bits) ; 
    $subnet = substr(IP2Bin($subnet),0,$bits) ; 
    return ($ip == $subnet) ; 
} 

function IP2Bin($ip){ 
    $ipbin = ''; 
    $ips = explode(".",$ip) ; 
    foreach ($ips as $iptmp){ 
     $ipbin .= sprintf("%08b",$iptmp) ; 
    } 
    return $ipbin ; 
} 
37

Tôi đã tìm thấy nhiều phương pháp sau đây phá vỡ sau PHP 5.2. Tuy nhiên, giải pháp sau đây hoạt động trên các phiên bản 5.2 trở lên:

function cidr_match($ip, $cidr) 
{ 
    list($subnet, $mask) = explode('/', $cidr); 

    if ((ip2long($ip) & ~((1 << (32 - $mask)) - 1)) == ip2long($subnet)) 
    { 
     return true; 
    } 

    return false; 
} 

Ví dụ kết quả

 
cidr_match("1.2.3.4", "0.0.0.0/0"):   true 
cidr_match("127.0.0.1", "127.0.0.1/32"): true 
cidr_match("127.0.0.1", "127.0.0.2/32"): false 

Nguồn http://www.php.net/manual/en/function.ip2long.php#82397.

+2

Xác nhận làm việc trên PHP 5.6.5. (Windows x86_64) – Adambean

+0

'cidr_match (" 1.2.3.4 "," 0.0.0.0/0 ")' trả về false trên máy của tôi (PHP 5.5.13, Windows x64). –

+1

Đây phải là câu trả lời được chấp nhận. +1! – Sw0ut

1

Chỉ cần lưu ý, câu trả lời của Alnitak hoạt động 32/64 bit.

Đây là phiên bản đã được nấu, để bảo vệ chống spam nhanh chóng dựa trên danh sách IP quốc gia mà bạn có thể nhận được ở khắp mọi nơi. google cho danh sách ip quốc gia hoặc quốc gia ip khối (Phải cung cấp cho một ở đây, thực sự khó khăn để tìm thấy nó trong trang đó chuyển hướng trang: Country ip block generator)

Sao chép danh sách ip cidr của bạn vào chuỗi $ cidrs. Và đặt mã này ngay trước trang html, có thể trong tệp header.php.

Cũng có thể được sử dụng để lọc sử dụng adsense trong các mẫu trang dựa trên quốc gia.

Đây chỉ là giải pháp cấp bách trong đêm. Đôi khi người ta cần phải đưa ra một cái gì đó như thế này cho một khách hàng một cách nhanh chóng ngày hôm qua, vì vậy ở đây nó được.

//++++++++++++++++++++++ 
//COUNTRY SPAM PROTECTOR 
//speed: ~5ms @ 2000 cidrs 
//comments start with # 
//++++++++++++++++++++++ 
$cidrs= 
' 
#yourcountry 
1.3.4.5/21 
#mycountry 
6.7.8.9/20 
'; 
//$cidrs.="\n".'123.12.12.12/32';//test, your ip 
$cidrs_ar=preg_split('/\s+/',$cidrs,-1,PREG_SPLIT_NO_EMPTY); 
[email protected]$_SERVER['REMOTE_ADDR']; 
$iplong=ip2long($ip); 
//var_export($cidrs_ar);var_export($ip);var_export($iplong); 
if($iplong) 
    foreach($cidrs_ar as $cidr) 
    { 
    $ar=explode ('/', $cidr); 
    $netiplong=ip2long($ar[0]); 
    if($netiplong===false) continue; 
    $mask=intval(@$ar[1]); 
    if(!$mask) continue; 
    $bitmask=-1 <<(32-$mask); 
    if(($iplong & $bitmask) == ($netiplong & $bitmask)) 
     { 
     header('Location: http://www.someotherwebsite.com/',true,303); 
     exit; 
     } 
    } 
1

Bạn cũng có thể sử dụng Net_IPv4 PEAR library.

function cidr_match($ip, $net){ 
    include_once("Net/IPv4.php"); 
    $objIP = new Net_IPv4(); 
    return $objIP->ipInNetwork($ip, $net); 
} 
2

Tôi cũng cần kiểm tra IP chống lại mặt nạ CIDR. Tôi đã tìm thấy một trang web với lời giải thích tuyệt vời và mã nguồn hoạt động hoàn hảo tốt.

Trang web http://pgregg.com/blog/2009/04/php-algorithms-determining-if-an-ip-is-within-a-specific-range/

Bởi vì trang web có thể một ngày nào đó không còn tồn tại, đây là mã

<?php 

/* 
* ip_in_range.php - Function to determine if an IP is located in a 
*     specific range as specified via several alternative 
*     formats. 
* 
* Network ranges can be specified as: 
* 1. Wildcard format:  1.2.3.* 
* 2. CIDR format:   1.2.3/24 OR 1.2.3.4/255.255.255.0 
* 3. Start-End IP format: 1.2.3.0-1.2.3.255 
* 
* Return value BOOLEAN : ip_in_range($ip, $range); 
* 
* Copyright 2008: Paul Gregg <[email protected]> 
* 10 January 2008 
* Version: 1.2 
* 
* Source website: http://www.pgregg.com/projects/php/ip_in_range/ 
* Version 1.2 
* 
* This software is Donationware - if you feel you have benefited from 
* the use of this tool then please consider a donation. The value of 
* which is entirely left up to your discretion. 
* http://www.pgregg.com/donate/ 
* 
* Please do not remove this header, or source attibution from this file. 
*/ 


// decbin32 
// In order to simplify working with IP addresses (in binary) and their 
// netmasks, it is easier to ensure that the binary strings are padded 
// with zeros out to 32 characters - IP addresses are 32 bit numbers 
Function decbin32 ($dec) { 
    return str_pad(decbin($dec), 32, '0', STR_PAD_LEFT); 
} 

// ip_in_range 
// This function takes 2 arguments, an IP address and a "range" in several 
// different formats. 
// Network ranges can be specified as: 
// 1. Wildcard format:  1.2.3.* 
// 2. CIDR format:   1.2.3/24 OR 1.2.3.4/255.255.255.0 
// 3. Start-End IP format: 1.2.3.0-1.2.3.255 
// The function will return true if the supplied IP is within the range. 
// Note little validation is done on the range inputs - it expects you to 
// use one of the above 3 formats. 
Function ip_in_range($ip, $range) { 
    if (strpos($range, '/') !== false) { 
    // $range is in IP/NETMASK format 
    list($range, $netmask) = explode('/', $range, 2); 
    if (strpos($netmask, '.') !== false) { 
     // $netmask is a 255.255.0.0 format 
     $netmask = str_replace('*', '0', $netmask); 
     $netmask_dec = ip2long($netmask); 
     return ((ip2long($ip) & $netmask_dec) == (ip2long($range) & $netmask_dec)); 
    } else { 
     // $netmask is a CIDR size block 
     // fix the range argument 
     $x = explode('.', $range); 
     while(count($x)<4) $x[] = '0'; 
     list($a,$b,$c,$d) = $x; 
     $range = sprintf("%u.%u.%u.%u", empty($a)?'0':$a, empty($b)?'0':$b,empty($c)?'0':$c,empty($d)?'0':$d); 
     $range_dec = ip2long($range); 
     $ip_dec = ip2long($ip); 

     # Strategy 1 - Create the netmask with 'netmask' 1s and then fill it to 32 with 0s 
     #$netmask_dec = bindec(str_pad('', $netmask, '1') . str_pad('', 32-$netmask, '0')); 

     # Strategy 2 - Use math to create it 
     $wildcard_dec = pow(2, (32-$netmask)) - 1; 
     $netmask_dec = ~ $wildcard_dec; 

     return (($ip_dec & $netmask_dec) == ($range_dec & $netmask_dec)); 
    } 
    } else { 
    // range might be 255.255.*.* or 1.2.3.0-1.2.3.255 
    if (strpos($range, '*') !==false) { // a.b.*.* format 
     // Just convert to A-B format by setting * to 0 for A and 255 for B 
     $lower = str_replace('*', '0', $range); 
     $upper = str_replace('*', '255', $range); 
     $range = "$lower-$upper"; 
    } 

    if (strpos($range, '-')!==false) { // A-B format 
     list($lower, $upper) = explode('-', $range, 2); 
     $lower_dec = (float)sprintf("%u",ip2long($lower)); 
     $upper_dec = (float)sprintf("%u",ip2long($upper)); 
     $ip_dec = (float)sprintf("%u",ip2long($ip)); 
     return (($ip_dec>=$lower_dec) && ($ip_dec<=$upper_dec)); 
    } 

    echo 'Range argument is not in 1.2.3.4/24 or 1.2.3.4/255.255.255.0 format'; 
    return false; 
    } 

} 
?> 

(tôi đã không phát triển này, điều này được phát triển bởi Paul Gregg (http://pgregg.com/)

37

Trong tình huống tương tự, tôi đã sử dụng symfony/http-foundation.

Khi sử dụng gói này, cá tuyết của bạn e sẽ trông giống như:

$ips = array('10.2.1.100', '10.2.1.101', '10.5.1.100', '1.2.3.4'); 

foreach($ips as $IP) { 
    if (\Symfony\Component\HttpFoundation\IpUtils::checkIp($_SERVER['REMOTE_ADDR'], '10.2.0.0/16')) { 
     print "you're in the 10.2 subnet\n"; 
    } 
} 

Nó cũng xử lý IPv6.

Link: https://packagist.org/packages/symfony/http-foundation

+0

Cảm ơn!Bằng cách nào đó giải pháp Symfony hoạt động chính xác trong trường hợp của tôi, trong khi chấp nhận một - không. – Xardas

+0

Thats bởi vì PHP, nhà soạn nhạc, và giao hưởng rất khác nhau trở lại khi câu hỏi được yêu cầu trong năm 2009 – Uberfuzzy

+1

Đây là câu trả lời hay nhất IMO. – Tek

1

Có lẽ nó rất hữu ích cho một ai đó.

Chuyển đổi chút mặt nạ vào mặt nạ IP: mặt nạ IP

// convert 12 => 255.240.0.0 
// ip2long('255.255.255.255') == -1 
$ip = long2ip((-1 << (32 - $bit)) & -1); 

Chuyển đổi thành mặt nạ bit:

// convert 255.240.0.0 => 12 

// is valid IP 
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) === false) { 
    throw new \InvalidArgumentException(sprintf('Invalid IP "%s".', $ip)); 
} 

// convert decimal to binary 
$mask = ''; 
foreach (explode('.', $ip) as $octet) { 
    $mask .= str_pad(decbin($octet), 8, '0', STR_PAD_LEFT); 
} 

// check mask 
if (strpos('01', $mask) !== false) { 
    // valid 11111111111111111111111100000000 -> 255.255.255.0 
    // invalid 11111111111111111111111100000001 -> 255.255.255.1 
    throw new \InvalidArgumentException(sprintf('IP mask "%s" is not valid.', $ip)); 
} 

$bit = substr_count($mask, '1'); // bit mask 
2

Đây là một chức năng 64bits nhanh để làm điều đó, hãy bình luận dòng trở lại bạn don' t cần. Chấp nhận bất kỳ IPv4 hợp lệ có hoặc không có giá trị CIDR Routing Prefix ví dụ 63.161.156.0/ hoặc 63.161.156.0

<?php 
function cidr2range($ipv4){ 
if ($ip=strpos($ipv4,'/')) 
{$n_ip=(1<<(32-substr($ipv4,1+$ip)))-1; $ip_dec=ip2long(substr($ipv4,0,$ip)); } 
else 
{$n_ip=0;         $ip_dec=ip2long($ipv4);    } 
$ip_min=$ip_dec&~$n_ip; 
$ip_max=$ip_min+$n_ip; 
#Array(2) of Decimal Values Range 
return [$ip_min,$ip_max]; 
#Array(2) of Ipv4 Human Readable Range 
return [long2ip($ip_min),long2ip($ip_max)]; 
#Array(2) of Ipv4 and Subnet Range 
return [long2ip($ip_min),long2ip(~$n_ip)]; 
#Array(2) of Ipv4 and Wildcard Bits 
return [long2ip($ip_min),long2ip($n_ip)]; 
#Integer Number of Ipv4 in Range 
return ++$n_ip; 
} 

Để tiến nhanh về kiểm tra xem một cho ipv4 là phù hợp với một CIDR cho bạn có thể làm điều đó inline như trong ví dụ này

<?php 
$given_cidr='55.55.55.0/24'; 
$given_ipv4='55.55.55.55'; 
if(($range=cidr2range($given_cidr)) && 
($check=ip2long($given_ipv4))!==false && 
$check>=$range[0] && $check<=$range[1]) 
{ 
echo 'Yes, '.$given_ipv4.' is included in '.$given_cidr; 
} 
else 
{ 
echo 'No, '.$given_ipv4.' is not included in '.$given_cidr; 
} 

để có được đầy đủ phạm vi như một mảng cho một IP nhất định (có hoặc không có CIDR Routing Prefix), bạn có thể sử dụng đoạn mã sau nhưng hãy cẩn thận vì ví dụ 25.25.25.25/16 trả về một mảng với 65536 yếu tố và bạn có thể dễ dàng chạy ra khỏi bộ nhớ sử dụng một Routing nhỏ Prefix

<?php 
$result=cidr2range($ipv4); 
for($ip_dec=$result[0];$ip_dec<=$result[1];$ip_dec++) 
$full_range[$ip_dec]=long2ip($ip_dec); 
print_r($full_range); 

Để tiến nhanh về kiểm tra xem một cho ipv4 là phù hợp với một mảng nhất định IP (có hoặc không có CIDR Routing Prefix)

<?php 
#This code is checking if a given ip belongs to googlebot 
$given_ipv4='74.125.61.208'; 
$given_cidr_array=['108.59.93.43/32','108.59.93.40/31','108.59.93.44/30','108.59.93.32/29','108.59.93.48/28','108.59.93.0/27','108.59.93.64/26','108.59.93.192/26','108.59.92.192/27','108.59.92.128/26','108.59.92.96/27','108.59.92.0/27','108.59.94.208/29','108.59.94.192/28','108.59.94.240/28','108.59.94.128/26','108.59.94.16/29','108.59.94.0/28','108.59.94.32/27','108.59.94.64/26','108.59.95.0/24','108.59.88.0/22','108.59.81.0/27','108.59.80.0/24','108.59.82.0/23','108.59.84.0/22','108.170.217.128/28','108.170.217.160/27','108.170.217.192/26','108.170.217.0/25','108.170.216.0/24','108.170.218.0/23','108.170.220.0/22','108.170.208.0/21','108.170.192.0/20','108.170.224.0/19','108.177.0.0/17','104.132.0.0/14','104.154.0.0/15','104.196.0.0/14','107.167.160.0/19','107.178.192.0/18','125.17.82.112/30','125.16.7.72/30','74.125.0.0/16','72.14.192.0/18','77.109.131.208/28','77.67.50.32/27','66.102.0.0/20','66.227.77.144/29','66.249.64.0/19','67.148.177.136/29','64.124.98.104/29','64.71.148.240/29','64.68.64.64/26','64.68.80.0/20','64.41.221.192/28','64.41.146.208/28','64.9.224.0/19','64.233.160.0/19','65.171.1.144/28','65.170.13.0/28','65.167.144.64/28','65.220.13.0/24','65.216.183.0/24','70.32.132.0/23','70.32.128.0/22','70.32.136.0/21','70.32.144.0/20','85.182.250.128/26','85.182.250.0/25','80.239.168.192/26','80.149.20.0/25','61.246.224.136/30','61.246.190.124/30','63.237.119.112/29','63.226.245.56/29','63.158.137.224/29','63.166.17.128/25','63.161.156.0/24','63.88.22.0/23','41.206.188.128/26','12.234.149.240/29','12.216.80.0/24','8.34.217.24/29','8.34.217.0/28','8.34.217.32/27','8.34.217.64/26','8.34.217.128/25','8.34.216.0/24','8.34.218.0/23','8.34.220.0/22','8.34.208.128/29','8.34.208.144/28','8.34.208.160/27','8.34.208.192/26','8.34.208.0/25','8.34.209.0/24','8.34.210.0/23','8.34.212.0/22','8.35.195.128/28','8.35.195.160/27','8.35.195.192/26','8.35.195.0/25','8.35.194.0/24','8.35.192.0/23','8.35.196.0/22','8.35.200.0/21','8.8.8.0/24','8.8.4.0/24','8.6.48.0/21','4.3.2.0/24','23.236.48.0/20','23.251.128.0/19','216.239.32.0/19','216.252.220.0/22','216.136.145.128/27','216.33.229.160/29','216.33.229.144/29','216.34.7.176/28','216.58.192.0/19','216.109.75.80/28','216.74.130.48/28','216.74.153.0/27','217.118.234.96/28','208.46.199.160/29','208.44.48.240/29','208.21.209.0/28','208.184.125.240/28','209.185.108.128/25','209.85.128.0/17','213.200.103.128/26','213.200.99.192/26','213.155.151.128/26','199.192.112.224/29','199.192.112.192/27','199.192.112.128/26','199.192.112.0/25','199.192.113.176/28','199.192.113.128/27','199.192.113.192/26','199.192.113.0/25','199.192.115.80/28','199.192.115.96/27','199.192.115.0/28','199.192.115.128/25','199.192.114.192/26','199.192.114.0/25','199.223.232.0/21','198.108.100.192/28','195.16.45.144/29','192.104.160.0/23','192.158.28.0/22','192.178.0.0/15','206.160.135.240/28','207.223.160.0/20','203.222.167.144/28','173.255.125.72/29','173.255.125.80/28','173.255.125.96/27','173.255.125.0/27','173.255.125.128/25','173.255.124.240/29','173.255.124.232/29','173.255.124.192/27','173.255.124.128/29','173.255.124.144/28','173.255.124.160/27','173.255.124.48/29','173.255.124.32/28','173.255.124.0/27','173.255.124.64/26','173.255.126.0/23','173.255.122.128/26','173.255.122.64/26','173.255.123.0/24','173.255.121.128/26','173.255.121.0/25','173.255.120.0/24','173.255.117.32/27','173.255.117.64/26','173.255.117.128/25','173.255.116.192/27','173.255.116.128/26','173.255.116.0/25','173.255.118.0/23','173.255.112.0/22','173.194.0.0/16','172.102.8.0/21','172.253.0.0/16','172.217.0.0/16','162.216.148.0/22','162.222.176.0/21','180.87.33.64/26','128.177.109.0/26','128.177.119.128/25','128.177.163.0/25','130.211.0.0/16','142.250.0.0/15','146.148.0.0/17']; 
echo '<pre>'; 
$in_range=false; 
if (($given_ipv4_dec=ip2long($given_ipv4))!==false) 
{ 
foreach($given_cidr_array as $given_cidr){ 
if(($range=cidr2range($given_cidr)) && 
$given_ipv4_dec>=$range[0] && $given_ipv4_dec<=$range[1]) 
{ 
$in_range=true; 
echo $given_ipv4.' matched '.$given_cidr.' ('.join(array_map('long2ip',$range),' - ').")\n"; 
} 
} 
} 
echo $given_ipv4.' is probably'.($in_range?'':' not').' a Googlebot IP'; 

Để chạy nhanh các chức năng không kiểm tra đầu vào nhưng chính thức nó phải là một chuỗi phù hợp với những điều sau regex

#^(?:((?:0)|(?:2(?:(?:[0-4][0-9])|(?:5[0-5])))|(?:1?[0-9]{1,2}))\.((?:0)|(?:2(?:(?:[0-4][0-9])|(?:5[0-5])))|(?:1?[0-9]{1,2}))\.((?:0)|(?:2(?:(?:[0-4][0-9])|(?:5[0-5])))|(?:1?[0-9]{1,2}))\.((?:0)|(?:2(?:(?:[0-4][0-9])|(?:5[0-5])))|(?:1?[0-9]{1,2}))(?:/((?:(?:0)|(?:3[0-2])|(?:[1-2]?[0-9]))))?)$# 

Nếu bạn muốn xác minh các đầu vào trước khi sử dụng chức năng

<?php 
if (is_string($ipv4) && preg_match('#^(?:((?:0)|(?:2(?:(?:[0-4][0-9])|(?:5[0-5])))|(?:1?[0-9]{1,2}))\.((?:0)|(?:2(?:(?:[0-4][0-9])|(?:5[0-5])))|(?:1?[0-9]{1,2}))\.((?:0)|(?:2(?:(?:[0-4][0-9])|(?:5[0-5])))|(?:1?[0-9]{1,2}))\.((?:0)|(?:2(?:(?:[0-4][0-9])|(?:5[0-5])))|(?:1?[0-9]{1,2}))(?:/((?:(?:0)|(?:3[0-2])|(?:[1-2]?[0-9]))))?)$#',$ipv4)) 
{ 
#This is a valid ipv4 with or without CIDR Routing Prefix 
$result=cidr2range($ipv4); 
print_r($result); 
} 

Sau đó câu trả lời chính thức cho câu hỏi của bạn là sau

<?php 
#Requiring cidr2range shown above function 
function cidr_match($mixed_ip,$mixed_cidr){ 
if (!is_array($mixed_ip)){ 
$string_mode=true; 
$mixed_ip=[$mixed_ip=>0]; 
} 
else $mixed_ip=array_fill_keys($mixed_ip,0); 
if (!is_array($mixed_cidr)) $mixed_cidr=[$mixed_cidr]; 
foreach($mixed_ip as $ip => &$result) 
foreach($mixed_cidr as $cidr) 
{ 
if(($range=cidr2range($cidr)) && 
($check=ip2long($ip))!==false && 
$check>=$range[0] && $check<=$range[1]){ 
$result=$cidr; 
break; 
} 
} 
$mixed_ip=array_filter($mixed_ip); 
return $string_mode?($mixed_ip?true:false):$mixed_ip; 
} 

print '<pre>'; 

#Your example 
$ips = array('10.2.1.100', '10.2.1.101', '10.5.1.100', '1.2.3.4'); 

foreach ($ips as $IP) { 
    if (cidr_match($IP, '10.2.0.0/16') == true) { 
     print "you're in the 10.2 subnet\n"; 
    } 
} 


#Also working with IP array and/or CIDR array 
#If IP array is given then return an array containing IP (keys) matching CIDR (values) 
$result=cidr_match($ips,['20.2.0.0/16','10.2.0.0/15']); 
foreach($result as $ip => $cidr){ 
print "$ip is in the $cidr subnet\n"; 
} 

Bạn có thể biên dịch chức năng của riêng bạn sử dụng các ví dụ, hy vọng vài dòng này đã giúp bạn…

Các vấn đề liên quan