如何使用 PHP 检查传入 IP 是否在子网掩码内?

问题描述 投票:0回答:1

我有一个 Laravel 应用程序,我在其中为 API 路由创建了中间件,以根据 .env 文件中存储的 IP 地址白名单检查请求 IP(我想将 IP 存储在数据库表中,但不确定最佳方法存储带有子网的 IP 地址,但这是另一天的问题)。

我现在需要将带有子网掩码的IP添加到白名单中。如何修改下面的代码来检查请求IP是否在子网范围内?

$requestIP = '12.23.34.56';

// Original array of IP addresses
// $whitelist = collect([
//   '127.0.0.1',
// ]);

$whitelist = collect([
   '127.0.0.1',
   '12.23.34.0/27'
]);

if ($whitelist->contains($request->ip())) {
    return $next($request);
}

abort(response('Unauthorized IP', 403));
php ip subnet
1个回答
0
投票

这里有一个解决方案,但仅适用于 IPv4,且仅适用于 64 位系统。

<?PHP

$testlist = [
    '127.0.0.1',
    '127.0.0.2',
    '12.23.34.1',
    '12.23.34.56',
    '12.23.35.56',
];

$whitelist = [
    '127.0.0.1',
    '12.23.34.0/27',
];

function checkip ( $ip )
{
    global $whitelist;

    //--- convert whilelist to a data structure for faster checks
    static $reflist = NULL;
    if (!isset($reflist))
    {
        $reflist = [];
        foreach ( $whitelist as $allow )
        {
            $p = strpos($allow,'/');
            if ( $p === false )
            {
                $num = ip2long($allow);
                $bits = 32;
            }
            else
            {
                $num = ip2long(substr($allow,0,$p));
                $bits = intval(substr($allow,$p+1));
            }
            if ( $num !== false && $bits > 0 && $bits <= 32 )
            {
                $mask = ( 0xffffffff<<(32-$bits) ) & 0xffffffff;
                printf("%08x %08x\n",$num&$mask,$mask);
                $reflist[] = [$num&$mask,$mask];
            }
        }
    }

    //---check ipv4
    $ip = ip2long($ip);
    if ( $ip !== false )
    {
        foreach ( $reflist as $d )
            if ( $d[0] == ( $ip & $d[1] ))
                return true;
    }

    return false;
}

foreach ( $testlist as $ip )
    printf("%15s : %d\n",$ip,checkip($ip));

?>
© www.soinside.com 2019 - 2024. All rights reserved.