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

时间:2015-09-22 15:14:25

标签: php

我有来自Microsoft Azure数据中心(http://www.microsoft.com/en-us/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

1 个答案:

答案 0 :(得分: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

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

更新:抱歉,在我输入答案时错过了上述评论。

@ Ukuser32,是的,使用ip2long将点分十进制转换为长整数(更容易使用;在数据库中存储长整数)。要获得范围的结束,请查看CIDR的第2部分。从左侧开始的位数(N)固定在该范围内。这意味着32-N是可变位的数量。这意味着该范围内有2 **(32-N)ips。这意味着可以计算$ 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];
}