在PHP 5中将IP与CIDR掩码匹配?

Ube*_*zzy 51 php cidr

我正在寻找快速/简单的方法来匹配给定的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"; 
    }
}
Run Code Online (Sandbox Code Playgroud)

会是什么cidr_match()模样?

它并不一定非常简单,但快速会很好.任何只使用内置/通用功能的东西都是奖励(因为我很可能会让一个人向我展示梨的东西,但是我不能依赖梨或者我的代码所在的地方安装的包部署).

Aln*_*tak 73

如果仅使用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;
}
Run Code Online (Sandbox Code Playgroud)

  • 这不适用于32位系统:match(1.2.3.4,0.0.0.0/0)返回false,应返回true (3认同)
  • @Guillaume - 你确定吗?重要的是,正确的最低有效位为零.您将在64位计算机上获得的额外高位将被忽略. (2认同)

Dáv*_*zki 47

在类似的情况下,我最终使用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";
    }
}
Run Code Online (Sandbox Code Playgroud)

它还处理IPv6.

链接:https://packagist.org/packages/symfony/http-foundation

  • 如果您使用基于 symphony 的框架(如 laravel),就是这种方式 (2认同)

Sam*_*son 44

我发现许多这些方法在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;
}
Run Code Online (Sandbox Code Playgroud)

示例结果

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.

  • 确认在PHP 5.6.5上工作.(Windows x86_64) (2认同)
  • `PHP 7.1.2 x86_64`为我工作,谢谢!+1 (2认同)

Dec*_*bal 5

一些功能改变了:

  • 分裂与爆炸

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;
}
Run Code Online (Sandbox Code Playgroud)