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


Get all IP addresses in a range in PHP

我有900多个来自Microsoft Azure数据中心(http://www.microsoft.com/en-us/download/confirmation.aspx?id=41653)的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

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

创建一个列为"range_start"answers"range_end"的表,并在这些列上建立索引。对于每个IP地址范围,插入一行,其中包含范围的开始和结束。完成后,您将拥有不到1000行。现在,要测试IP地址…

SELECT * FROM IP_RANGES WHERE $testIP>=range_start AND $testIP<=range_end

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

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

@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];
}