网络与 IP

CIDR 是什么意思:无类域间路由与 /n 斜线写法

CIDR(Classless Inter-Domain Routing,无类域间路由)是 1993 年起取代 A、B、C 类地址的分配与路由方式:网络部分不再固定为 8、16、24 位,而是写在斜线后面。/22 就表示前 22 位固定、后 10 位可变,即一个含 1,024 个地址的块。

作者 顶联产品团队发布于 5 分钟阅读

CIDR 是什么意思:它是 Classless Inter-Domain Routing 的缩写,中文叫无类域间路由,是今天互联网分配 IP 地址和做路由的基本规则。它做了两件事:一是取消 A、B、C 类对网络位长度的限制,网络部分可以是 0 到 32 之间的任意位数,写在地址后面的斜线里,例如 172.18.20.0/22;二是允许把连续的地址块汇总成一条路由。日常说的“CIDR 写法”“CIDR 地址块”,指的就是这种“起始地址/前缀长度”的表示法,它同时说清了一个块从哪里开始、有多大。

有类地址为什么被 CIDR 取代

CIDR 之前,IPv4 地址按第一个字节分类,网络位只有三种长度:

类别 首字节范围 网络位 这一类共有多少个网络 每个网络可用主机数
A 类 1–126 8 位 126 16,777,214
B 类 128–191 16 位 16,384 65,534
C 类 192–223 24 位 2,097,152 254

问题出在档位太粗。一个需要 2,000 台主机的单位,C 类的 254 个不够用,只能申请 B 类,结果 65,534 个地址只用了约 3%。B 类总共只有 16,384 个,按这种方式发放,很快就不够分了;退而求其次,给这个单位发 8 个 C 类,地址省下了,可每个 C 类都要在互联网路由器上单独占一条路由,路由表随之膨胀。

1993 年发布的 RFC 1519 把当时的困境概括为三点:B 类地址即将耗尽、互联网路由器上的路由表增长过快,超出现有软件和人力能够有效管理的程度、32 位地址空间终将用完。CIDR 针对前两点给出了办法:

  • 前缀长度任意:需要 2,000 个地址就给一个 /21(2,048 个地址,2,046 个可用),不必在 254 和 65,534 之间二选一。
  • 按层级分配、对外汇总:地址从注册机构分给运营商,再由运营商分给客户。运营商手里成百上千个客户的小块,对外只宣告一个汇总后的大前缀。

RFC 1519 后来被 2006 年的 RFC 4632 取代,规则延续至今。原来的“子网划分”只能在一个有类网络内部往小里切,CIDR 则让块可以比 /8、/16、/24 更大或更小,地址和路由都只看前缀长度,不再看第一个字节。

/n 怎么读:前 n 位固定,剩下的可变

CIDR 写法 地址/n 的意思是:32 位地址里,前 n 位是网络前缀,块内所有地址的这 n 位都相同;后面 32 − n 位可以任意变化。由此直接得到三个数:

  • 块大小:2 的(32 − n)次方。/22 是 2^10 = 1,024 个地址。
  • 掩码:n 个 1 后面补 0。/22 是 255.255.252.0。
  • 起点:起始地址必须让后 32 − n 位全为 0,也就是块大小的整数倍。

n 正好是 8、16、24 时最直观,斜线前面的地址按点对齐,/24 就是前三节固定、第四节从 0 到 255。n 不是 8 的倍数时,有一个字节会被前缀切成两半,这个字节决定了块的边界。前缀在 /17 到 /24 之间,被切开的是第三节:

前缀 第三节的步长 一个 /16 里能分出几个 第三节的合法起点 块大小
/17 128 2 0、128 32,768
/18 64 4 0、64、128、192 16,384
/19 32 8 0、32、64……224 8,192
/20 16 16 0、16、32……240 4,096
/21 8 32 0、8、16……248 2,048
/22 4 64 0、4、8……252 1,024
/23 2 128 所有偶数 512
/24 1 256 0–255 任意 256

/25 到 /32 的规律完全相同,只是被切开的换成第四节:/25 步长 128,/26 步长 64,一直到 /30 步长 4。任何前缀都能现场推出步长:先求 n 除以 8 的余数 r,步长就是 2 的(8 − r)次方。例如 /22 的 r = 6,步长 2^2 = 4;/27 的 r = 3,第四节步长 2^5 = 32。r 为 0 说明正好按字节对齐,不需要这个公式。

非整字节的例子:/22 和 /23 怎么看

例一:172.18.20.0/22 包含哪些地址。 22 − 16 = 6,第三节的前 6 位属于前缀,后 2 位和第四节的 8 位一起可变:

172.18.20.0/22
第三节 20 = 000101|00    前 6 位固定(16 + 6 = 22)
                   ^^    这 2 位加上第四节 8 位,共 10 位可变
第三节可取 000101 00、01、10、11,即 20、21、22、23
范围:172.18.20.0 ~ 172.18.23.255,共 2^10 = 1,024 个地址

所以 /22 等于 4 个连续的 /24,第三节从 20 到 23。作为一个子网使用时,网络地址是 172.18.20.0,广播地址是 172.18.23.255,中间 1,022 个都能分配。

例二:172.18.27.130/22 属于哪个块。 看第三节,/22 的步长是 4,27 除以 4 得 6 余 3,块从 6 × 4 = 24 开始,所以它属于 172.18.24.0/22,范围 172.18.24.0 到 172.18.27.255。

例三:172.18.26.0/23。 步长 2,第三节 26 是偶数,合法起点。范围是 172.18.26.0 到 172.18.27.255,共 512 个地址。在这个块里,172.18.26.255 和 172.18.27.0 都是普通的主机地址,可以分给服务器;真正的广播地址只有末尾的 172.18.27.255。

这几个例子对应几种常见的误读:

写法 常见误读 实际含义
172.18.20.0/22 只有 172.18.20.x 这一段 20、21、22、23 四个 /24
172.18.22.0/22 一个从第三节 22 开始的块 22 不是 4 的倍数,不是合法起点;这个地址落在 172.18.20.0/22 里
172.18.26.0/23 里的 172.18.26.255 末位是 255,是广播地址 普通可用地址,广播地址是 172.18.27.255
任意两个相邻的 /24 都能合成一个 /23 只有第三节以偶数开头的一对才行,26 和 27 可以,27 和 28 不行

第三行在实际工作中最容易出事:一些写死了“末位 0 或 255 不能用”的表单校验和老脚本,会把 /23、/22 中间的这类地址误判为非法。分配地址前,按块的边界判断,不要按末位数字判断。

地址块和前缀:一个块只有一种合法写法

前缀和地址块是一回事的两种说法:前缀是块内所有地址共有的那 n 位,地址块是共有这 n 位的全部地址。所以一个合法的块只有一种写法,起点和长度都是唯一的。斜线前的地址如果不是块的起点,也就是主机位不全为 0,那它描述的就不是一个块,很多工具会直接拒绝:

# 主机位不为 0,作为路由目标是非法写法
$ ip route add 172.18.22.0/22 via 10.0.0.1
Error: Invalid prefix for given prefix length.

# Python 同样拒绝,报错的最后一行是:
$ python3 -c "import ipaddress; ipaddress.ip_network('172.18.22.0/22')"
ValueError: 172.18.22.0/22 has host bits set

# 加 strict=False,让它归到所在的块
$ python3 -c "import ipaddress; print(ipaddress.ip_network('172.18.22.0/22', strict=False))"
172.18.20.0/22

但同样的斜线写法配在网卡上就是合法的:ip addr add 172.18.22.15/22 dev eth0 的意思是“本机地址 172.18.22.15,所在块的前缀长度是 22”,系统会自动算出所在的网段 172.18.20.0/22 并加上直连路由。区分方法很简单:路由表、防火墙规则、分配单、IPAM 登记里写的是“块”,斜线前必须是起点;网卡配置里写的是“地址加前缀长度”,斜线前是主机自己的地址。

反过来,一段不按边界对齐的连续地址,不能用一个 CIDR 表示。例如 172.18.21.0 到 172.18.24.255,虽然恰好是 4 个 /24,但起点 21 不是 4 的倍数,凑不成一个 /22,最少要拆成三块:

$ python3 -c "import ipaddress as i; print(*i.summarize_address_range(i.ip_address('172.18.21.0'), i.ip_address('172.18.24.255')))"
172.18.21.0/24 172.18.22.0/23 172.18.24.0/24

拿到“从某某到某某”这种起止范围的分配单时,先用这条命令转换成 CIDR,再录入防火墙或路由配置。

路由器怎么用 CIDR:最长前缀匹配

有了任意长度的前缀,一个目的地址可能同时落在好几条路由里。路由器的规则是最长前缀匹配:能匹配上的路由中,前缀最长、也就是块最小、描述最具体的那条胜出。假设一台路由器上有这四条路由:

目的前缀 下一跳 能匹配 172.18.22.9 吗
0.0.0.0/0 10.0.0.1(出口) 能,/0 匹配一切
172.18.0.0/16 10.0.1.1 能
172.18.20.0/22 10.0.2.1 能,22 在 20~23 之间
172.18.22.0/24 10.0.3.1 能

发往 172.18.22.9 的包四条全中,选 /24,交给 10.0.3.1;发往 172.18.21.9 的包匹配不上 /24,选 /22,交给 10.0.2.1;发往 172.18.40.1 的只匹配 /16 和 /0,选 /16;8.8.8.8 只剩默认路由。想知道设备对某个地址实际选了哪条,直接问它:

# Linux:输出实际选中的下一跳和出接口
ip route get 172.18.22.9
# 172.18.22.9 via 10.0.3.1 dev eth0 src 10.0.0.10

华为和 H3C 用 display ip routing-table 172.18.22.9,思科用 show ip route 172.18.22.9,都会显示最终匹配的那条路由。

这条规则是 CIDR 汇总能成立的前提:运营商对外宣告一个大前缀,内部再用更长的前缀把流量分到各个客户,互不冲突。它也解释了机房里的一些常见现象,例如流量清洗服务在攻击期间对外宣告比原路由更长的前缀,就能把这部分地址的流量引到清洗中心;有人在内网配错了一条更具体的静态路由,大段地址里只有那一小块不通。

在 IPAM 里怎么落地

机房的地址台账里,最常见的错误不是不会算,而是写法不统一:有的段写起止地址,有的写 CIDR,有的把 172.18.22.0/22 这种非起点写法直接录进去,几年下来谁也说不清哪些块重叠了。

Toplink DCIM 的 IP 地址管理以 CIDR 为录入格式:填入一个段,系统自动算出开始地址、结束地址和子网掩码,网关可以选段内第一个或最后一个地址;/22、/21 这类大段可以自动拆成多个 /24 分别管理,每个段再记录所在机房、VLAN 和网关设备。IPv6 段同样按 CIDR 录入、按掩码拆分。地址按块登记之后,哪个块分给了谁、还剩多少,在用量比例图上一目了然。

常见问题

CIDR 和 VLSM 有什么区别?

VLSM(变长子网掩码)指在一个网络内部用不同长度的掩码划分子网;CIDR 指分配和路由时不再受 A、B、C 类限制,并允许把多个块汇总成一条路由。前者是内部划分的方法,后者是整个互联网的地址与路由规则,两者经常一起出现。

为什么说 CIDR 让路由表变小了?

连续且对齐的地址块可以汇总成一条前缀更短的路由,例如 4 个相邻的 /24 合成一条 /22。有类时代,同样的地址要用 4 条 C 类路由分别宣告。汇总要求块的数量是 2 的幂、地址连续、起点对齐,不满足时只能拆成多条。

IPv6 也用 CIDR 写法吗?

用,而且 IPv6 从设计之初就没有分类,只有前缀长度,例如 2001:db8:1200::/40。前缀长度范围是 0 到 128,局域网段通常固定用 /64,分配给机房或企业的常见 /48、/56。

想看看在你的机房里怎么用?

从一次产品演示开始,梳理你的业务链路。

查看价格
服务热线 400-112-2951

让我们聊聊你的 IDC 业务

扫码添加企业微信,预约产品演示或申请试用。

Toplink 企业微信二维码

长按保存或使用企业微信 / 微信扫描

也可致电
400-112-2951
Telegram
@TopLink88