检查 IP 是不是在 CIDR 网络掩码(范围)中

Posted

技术标签:

【中文标题】检查 IP 是不是在 CIDR 网络掩码(范围)中【英文标题】:Check if IP is in CIDR netmask (range)检查 IP 是否在 CIDR 网络掩码(范围)中 【发布时间】:2016-12-27 17:22:51 【问题描述】:

我有 2 张桌子 ipcidr

在第一个中,我存储了 IP。 (2列表,id,ip),这里是一个例子(值是虚构的):

id | ip
---+-------------
 1 | 172.922.2.10
---+-------------
 2 | 194.22.10.13

在第二个中,我存储 CIDR 网络掩码(2 列表,id,cidr),这是一个示例(值是虚构的):

id | cidr
---+-------------
 1 | 26.232.49.0/20
---+---------------
 2 | 14.44.182.0/24

有什么方法可以进行 mysql 查询来检查第一个表中的 ip 是否在我的任何 cidr 网络掩码的范围内?

注意:要将 cidr 网络掩码转换为 ip 的范围点击here

【问题讨论】:

【参考方案1】:

我个人建议使用 postgres,因为它具有 CIDR 数据类型和强大的功能,但也有关于在 MySQL 中做类似事情的有趣讨论。

http://planet.mysql.com/entry/?id=29283

【讨论】:

问题是我的共享主机不支持postgres。 真可惜。链接有帮助吗? 我现在就在上面,但最好在你的答案中写下解决方案,因为链接可能会在一段时间后消失,之后没有人可以从你的答案中得到任何好处。 公平评论。不过,我不确定如果我从那里复制和粘贴,这是否会被视为抄袭。 好吧,您也可以提及来源,我想没问题。或者您可以通过某种方式更改文本或更简单,IDK 抄袭的定义。【参考方案2】:

这出现在我的一个相关项目中,这似乎是该问题的最高 google 结果,所以,你得到了答案!

create function get_lowest_ipv4(cidr char(18)) returns bigint deterministic return INET_ATON(SUBSTRING_INDEX(cidr, '/', 1));
create function get_highest_ipv4(cidr char(18)) returns bigint deterministic return get_lowest_ipv4(cidr) + (0x100000000 >> SUBSTRING_INDEX(cidr,'/', -1)) - 1;

你可以这样做...from ip_map where INET_ATON("ip.add.re.ss") between get_lowest_ipv4(ip) AND get_highest_ipv4(ip)

因为您将函数声明为确定性,所以它会被缓存在 mysql 中,并且计算只需要运行一次。那么它只是“大于 y 且小于 x 的整数”,这实际上是即时的。

MySQL [astpp]> set @cidr="10.11.0.0/16";
Query OK, 0 rows affected (0.00 sec)

MySQL [astpp]> select get_lowest_ipv4(@cidr), get_highest_ipv4(@cidr), INET_NTOA(get_lowest_ipv4(@cidr)), INET_NTOA(get_highest_ipv4(@cidr));
+------------------------+-------------------------+-----------------------------------+------------------------------------+
| get_lowest_ipv4(@cidr) | get_highest_ipv4(@cidr) | INET_NTOA(get_lowest_ipv4(@cidr)) | INET_NTOA(get_highest_ipv4(@cidr)) |
+------------------------+-------------------------+-----------------------------------+------------------------------------+
|              168493056 |               168558591 | 10.11.0.0                         | 10.11.255.255                      |
+------------------------+-------------------------+-----------------------------------+------------------------------------+
1 row in set (0.00 sec)

MySQL [astpp]> set @cidr="10.11.12.1/32";
Query OK, 0 rows affected (0.00 sec)

MySQL [astpp]> select get_lowest_ipv4(@cidr), get_highest_ipv4(@cidr), INET_NTOA(get_lowest_ipv4(@cidr)), INET_NTOA(get_highest_ipv4(@cidr));
+------------------------+-------------------------+-----------------------------------+------------------------------------+
| get_lowest_ipv4(@cidr) | get_highest_ipv4(@cidr) | INET_NTOA(get_lowest_ipv4(@cidr)) | INET_NTOA(get_highest_ipv4(@cidr)) |
+------------------------+-------------------------+-----------------------------------+------------------------------------+
|              168496129 |               168496129 | 10.11.12.1                        | 10.11.12.1                         |
+------------------------+-------------------------+-----------------------------------+------------------------------------+
1 row in set (0.01 sec)

MySQL [astpp]>

唯一重要的警告是您插入了 VALID CIDR。例如,10.11.12.13/24 无效。这是 10.11.12.0/24 网络内的 IP 地址。

如果您在插入 CIDR 之前无法验证它们(出于某种疯狂的原因),您可以更改 get_lowest_ipv4 以对源进行按位比较,但这不太优雅。

INET_ATON(SUBSTRING_INDEX(`ip`, '/', 1)) & 0xffffffff ^((0x1 <<(32 -  SUBSTRING_INDEX(`ip`, '/', -1))) -1 )

是匹配无效 CIDR 的(未经测试的)尝试。

【讨论】:

以上是关于检查 IP 是不是在 CIDR 网络掩码(范围)中的主要内容,如果未能解决你的问题,请参考以下文章

IP 地址重叠/在 CIDR 范围内

CIDR与VLSM的区别

IP地址掩码以及CIDR掩码理解计算问题

IP地址NAT子网划分与子网掩码CIDR等网络层相关知识整理

IP地址NAT子网划分与子网掩码CIDR等网络层相关知识整理

子网掩码网络类型IP(IPV4)地址类型VLSM CIDR相关知识