检查 IP 是不是在 CIDR 网络掩码(范围)中
Posted
技术标签:
【中文标题】检查 IP 是不是在 CIDR 网络掩码(范围)中【英文标题】:Check if IP is in CIDR netmask (range)检查 IP 是否在 CIDR 网络掩码(范围)中 【发布时间】:2016-12-27 17:22:51 【问题描述】:我有 2 张桌子 ip
和 cidr
。
在第一个中,我存储了 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地址NAT子网划分与子网掩码CIDR等网络层相关知识整理