Javascript 判断 IP 地址是否属于 CIDR 范围
0x00 前言
在项目过程中,曾遇到根据 IP 地址判断 CIDR 网络区域、并且在前端展示的需求。由于 Javascript 没有原生类库能对 IP 地址进行相关操作,因此本文将采用 ES6 的新特性箭头函数,精简地实现此判断功能。
0x01 基础概念
什么是 CIDR?
CIDR(Classless Inter-Domain Routing,无类别域间路由)是一种 IP 地址归类方法,主要用于分配 IP 地址与有效地路由 IP 数据包等功能。
CIDR 的表示方法为 A.B.C.D/N,其中 A.B.C.D 是点分十进制的 IPv4 地址,N 是 0 至 32 之间的整数,代表 CIDR 的前缀长度,两者用斜线 / 分隔。
若一个 IP 地址的前 N 位与 一个 CIDR 范围的前缀相同,则说明此 IP 地址在此 CIDR 范围中。以 CIDR 范围 10.10.1.32/27 为例,可知 110.10.1.44 属于该 CIDR 范围,而 10.10.1.90 则不属于。

什么是箭头函数?
箭头函数表达式是 ECMAScript 6 的新增语法,相比于普通函数表达式,它主要特点是具有更精简的表达语法,以及在函数体内不存在自己的 this、arguments、super、new.target 等变量。
以下变量 a 与 b 均可定义了一个平方数计算函数,可见 a 比 b 的定义更精简:
1 | const a = x => x * x; |
箭头函数的特点及用法,请参考 0x03 中的相关教程,此处不再详解。
0x02 函数实现
validateIp4
validateIp4 用于判断 IPv4 地址的合法性。需要满足以下三个要求:
- 由三个
.符号分隔四部分整数 - 每部分整数范围是 0 至 255
- 每部分整数不能有前导 0
1 | const validateIp4 = ip => |
此函数通过正则表达式实现,其中:
(\d|[1-9]\d|1\d\d|2([0-4]\d|5[0-5]))限定每部分整数取值只能为 0 至 9、10 至 99、100 至 255(\.|$)限定每部分结尾只能是.符号或行尾
validateCidr
validateCidr 用于判断 CIDR 范围的合法性。除了 IPv4 部分需要满足上述三个要求,前缀长度还需满足:
- 长度范围是 0 至 32
- 长度不能有前导 0
1 | const validateCidr = cidr => |
由于 IPv4 地址最后一部分不再匹配行尾,因此正则表达式拆分成两部分:IPv4 地址前三部分末尾匹配 . 符号,最后一部分末尾匹配 / 符号。此外,(\d|[1-3]\d) 限定前缀范围为 0 至 32。
ip4ToInt
ip4ToInt 用于计算 IPv4 地址每部分整数的移位累加和。可以理解为,在去除 . 符号后,得到从左至右排列的 32 位二进制整数,再将其转换为十进制整数。
1 | const ip4ToInt = ip => |
由测试结果可见,函数暂未做 IPv4 地址合法性判断,适用于任何点分数字字符串,其中:
split('.')将 IPv4 地址的每部分取出,例如"192.168.1.1".split('.')将得到["192", "168", "1", "1"]reduce((sum, part) => (sum << 8) + parseInt(part, 10), 0)将计算每个数组元素的移位累加和,详细用法请参考:Array.prototype.reduce()sum为累加和,作为reduce函数的结果返回,初始值设置为 0part为每个数组元素,转换为十进制整数后,与左移 8 位后的sum相加
>>> 0将计算结果转换为 32 位无符号整数,详细含义请参考:What is the JavaScript >>> operator and how do you use it?
isIp4InCidr
isIp4InCidr 用于判断 IPv4 地址是否属于 CIDR 范围。函数中嵌套了子函数,isIp4InCidr(ip) 返回一个以 cidr 作为参数的函数,便于后续对多个 CIDR 范围进行判断。
1 | const isIp4InCidr = ip => cidr => { |
若 IPv4 地址与 CIDR 范围均合法,则继续进行判断,否则返回 false,其中:
[range, bits] = cidr.split('/')使用了 ES6 的新特性解构赋值,range为 CIDR 范围的 IPv4 部分,bits为前缀长度部分mask = ~(2 ** (32 - bits) - 1)根据前缀长度计算掩码,掩码的前bits位为1,后32 - bits位为0- 若
ip与range的前bits位相同,则返回true,否则返回false
isIp4InCidrs
isIp4InCidrs 用于判断 IPv4 地址是否属于 CIDR 数组内的其中一个范围。函数基于 isIp4InCidr 实现。
1 | const isIp4InCidrs = (ip, cidrs) => cidrs.some(isIp4InCidr(ip)); |
若 IPv4 地址属于CIDR 数组内的其中一个范围,则返回 true,结束判断,否则返回 false,其中:
some(isIp4InCidr(ip))将判断 CIDR 数组中,是否至少有一个元素满足isIp4InCidr(ip)为真,即 IPv4 地址属于某个 CIDR 范围,详细用法请参考:Array.prototype.some()
0x03 小结
本文主要是利用 ECMAScript 6 的新特性与 Array 对象的方法,精简地实现了 IPv4 地址是否属于某个 CIDR 范围的判断功能,文中不足或错误之处,恳请读者告知。
对功能实现与箭头函数有疑惑的读者,可参考以下文章:
Determining if an IPv4 address is within a CIDR range in JavaScript
ES6 In Depth: Arrow functions
ECMAScript 6 入门教程——函数的扩展