我正在寻找快速/简单的方法来匹配给定的IP4点分四核IP到CIDR表示法掩码.
我有一堆IP,我需要看看它们是否匹配一系列IP.
例:
$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"; } }
会是什么cidr_match()
模样?
它并不一定非常简单,但快速会很好.任何只使用内置/通用功能的东西都是奖励(因为我很可能会让一个人向我展示梨的东西,但是我不能依赖梨或者我的代码所在的地方安装的包部署).
如果仅使用IPv4:
用于ip2long()
将IP和子网范围转换为长整数
将/ xx转换为子网掩码
做一个按位'和'(即ip&mask)'并检查'result = subnet'
这样的事情应该有效:
function cidr_match($ip, $range) { list ($subnet, $bits) = explode('/', $range); if ($bits === null) { $bits = 32; } $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; }
在类似的情况下,我最终使用symfony/http-foundation.
使用此包时,您的代码如下所示:
$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"; } }
它还处理IPv6.
链接:https://packagist.org/packages/symfony/http-foundation
我发现许多这些方法在PHP 5.2之后破裂.但是,以下解决方案适用于5.2及更高版本:
function cidr_match($ip, $cidr) { list($subnet, $mask) = explode('/', $cidr); if ((ip2long($ip) & ~((1 << (32 - $mask)) - 1) ) == ip2long($subnet)) { return true; } return false; }
示例结果
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
来源http://www.php.net/manual/en/function.ip2long.php#82397.