获取PHP范围内的所有IP地址

Uku*_*r32 2 php

我有来自Microsoft Azure数据中心(http://www.microsoft.com/zh-cn/download/confirmation.aspx?id=41653)的900多个IP地址范围,我想确定IP地址是否来自这些地址之一。我已经将其转换为可以存储在文本文件中的单个列表。

因此:遍历每个地址并在此处使用IP2long()(例如第3点)是否更昂贵(https://mebsd.com/coding-snipits/php-ipcalc-coding-subnets-ip-addresses.html),或者最好转换范围内的所有IP地址,将它们存储在数据库中,然后查找它们?如果是后者,则如何实现这一目标(即将范围转换为其中的所有IP地址)?

对我来说,关键是它必须快速,因为我们会经常检查这一点。

IP地址/范围示例:

40.112.124.0/24
65.52.128.0/19
94.245.97.0/24
104.47.169.0/24
104.214.240.0/24
137.116.192.0/19
157.55.8.96/27
157.55.8.128/27
157.55.8.160/28
168.63.0.0/19
Run Code Online (Sandbox Code Playgroud)

Bar*_*der 5

哇,列表中几乎有1000个IP范围!为了优化验证单个IP地址是否在IP范围之一中,您绝对应该对IP范围列表进行一些预处理。创建数据库是一种方法。我会看一下SQLite,因为它是一种超快速的本地文件格式,对于像这样的只读任务,它比向运行数据库的另一个进程(或机器)发送查询要快。

创建一个包含“ range_start”和“ range_end”列以及这些列上的索引的表。对于每个IP地址范围,在范围的开头和结尾插入一行。完成后,您的行数将少于1000。现在,要测试IP地址...

SELECT * FROM IP_RANGES WHERE $testIP>=range_start AND $testIP<=range_end
Run Code Online (Sandbox Code Playgroud)

(修改此SQL语句以匹配您调用数据库的方式(最好使用PDO,最好使用SQL注入安全的方式))。

更新:对不起,我输入答案时错过了上面的评论。

@ Ukuser32,是的,用于ip2long将点分十进制转换为长整数(更容易使用;将长整数存储在数据库中)。要获得范围的结束,请查看CIDR的第二部分。从左边开始,是在该范围内固定的位数(N)。这意味着32-N是可变位数。这意味着该范围内有2 **(32-N)个ip。这意味着可以计算$ range_end ...

list($range_start, $range_end) = cidr2range('40.112.124.0/24');
echo "Start: $range_start, end: $range_end\n";

function cidr2range($cidr) {
    $cidr = explode('/', $cidr);
    $range_start = ip2long($cidr[0]);
    $range_end = $range_start + pow(2, 32-intval($cidr[1])) - 1;
    return [$range_start, $range_end];
}
Run Code Online (Sandbox Code Playgroud)