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

时间:2016-08-20 19:15:08

标签: mysql linux ip cidr

我有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

2 个答案:

答案 0 :(得分:0)

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

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

答案 1 :(得分: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&#39的整数,这将是有效的瞬间。

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。