检查IP是否在CIDR网络掩码(范围)内

3

我会翻译您的内容,涉及到IT技术。以下是需要翻译的内容:

我有两个表格,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范围,请单击此处
2个回答

0

真遗憾。链接有帮助吗? - tink
我正在处理这个问题,但最好在你的回答中写出解决方案,因为链接可能会在一段时间后消失,那时候就没有人能从你的回答中获益了。 - paulalexandru
公平的评论。我不确定如果我从那里复制粘贴是否会被视为抄袭。 - tink
你也可以提及来源,我想这应该没问题。或者你可以以某种方式更改文本或使其更简单,我不知道抄袭的定义。 - paulalexandru
一旦我在MySQL获得金牌,我就会加入你的行列 :p - Drew
显示剩余3条评论

0

这个问题在我的一个相关项目中出现过,而且这似乎是谷歌搜索结果中排名最高的答案,所以你得到了答案!

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]>

唯一需要注意的是插入有效的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 )

这是一个(未经测试的)尝试匹配无效的CIDRs。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接