📚 第七章 路由协议
📄 一句话概括

RIPv1 的报文里没有掩码字段,只能靠「主类网络」的老规矩猜。 跨主类边界时,子网路由会被汇总掉——不连续子网就出黑洞。

📝 本节和前面几节的关系

7.4.2 讲的逻辑没问题,但那是「掩码已知」的前提。 这一节说的坑,是 RIP2 存在的首要理由(7.4.5)。

一、报文里少了一个字段

RIPv1 的一条路由只有 20 字节:地址族、标记、IP 地址、保留、度量——没有掩码。 所以接收方拿到一个「10.1.0.0」,它不知道这是 /8、/16 还是 /24。 它只能按「有类地址」的老规矩猜: 10 开头是 A 类,就按 /8 算;172.16 到 172.31 是 B 类,按 /16;192.168 开头是 C 类,按 /24。 这套规矩在「没划子网」的年代是对的——但一旦划了子网,它就把不同的子网当成同一个。 注意这里有个缓冲机制: 在同一主类网络内部通告时,接收方会用「收到这个包的那个接口的掩码」来推断。 所以「同一个 10.0.0.0/8 内部的几个 /24」是能正确传的—— 前提是这几个子网用同一个掩码(也就是 FLSM,定长子网掩码)。

二、真正的坑在「跨主类边界」

RFC 1058 规定:跨越主类网络边界时,必须把子网路由汇总成主类网络。 所以一个 10.1.0.0/24 的路由,从 192.168 那边看过来,会变成 10.0.0.0/8。 这一步叫「自动汇总」,不是可选项,是强制的。 为什么必须汇总: 因为对面那台路由器如果只收到「10.1.0.0」,它没法判断这是 /8 的一个子网还是 /24 的一个网—— 它手上没有掩码信息,只能退回主类。 汇总至少保证「10 开头的东西在那边」,不至于完全丢。 正常情况下这没问题:如果所有 10 开头的网段都在同一个方向,汇总成一条反而更省。 问题出在「不连续子网」——10.1.0.0/24 在左边,10.2.0.0/24 在右边,中间隔着别的主类网络。 两边都往中间报「10.0.0.0/8」,中间那台就傻了:去 10.2 的包到底往左还是往右? 它只能选一条,另一半就成了黑洞。

三、为什么这个问题当年很常见

因为在 1990 年代,「一个公司用一个 A 类地址」是常态, 而公司又有多个办公点,中间靠专线或帧中继连。 每个办公点用 10.x.0.0/24,中间是运营商的网——这正好构成「不连续子网」。 于是「换个办公点访问不了另一个办公点」这种故障,在当年的网络里非常普遍。 三种补救办法,各有代价:

办法 做法 代价
改地址 让子网连续 要重编地址,停工
用静态路由 手工指明方向 不随拓扑变化
换协议 用 RIPv2 或 OSPF 要升级设备

第二行是当年最常见的临时办法:在两台边界路由器上各写一条静态路由,把对端子网指过去。 能用,但脆——因为静态路由不会随拓扑变化,链路一换就得手动改。 而且「网络里有一半是动态、一半是静态」这种混合状态,排错时最难查。

四、这个问题今天还在吗

RIP 少了,但「汇总」这件事一点没少。 今天 OSPF 和 BGP 都在做汇总,只是它们「能带掩码」, 所以可以「汇总到任意长度」而不必退到主类。 比如把 10.1.0.0/24 到 10.1.7.0/24 汇总成 10.1.0.0/21—— 这条前缀精确表达了「这八个 /24 在那边」,不会误伤别的。 但汇总的风险是一样的:只要汇总范围里有「其实不在那边」的地址,就会出黑洞。 所以工程上有条经验: 「汇总的边界要和地址规划的边界对齐」——地址分得好,汇总天然干净;地址分得乱,汇总必然漏。 这也是为什么「IP 地址规划」这件事,在今天看起来「地址多得用不完」的时代依然重要—— 不是怕不够用,是怕没法汇总。

五、动手 Demo:RIPv1 不带掩码会出什么事

三个 10.x.0.0/24 的子网,看 RIPv1 跨越主类边界时报出去变成什么。 注意它们是「被压成一条」,不是「各报一条」。

import ipaddress

subs = ['10.1.0.0/24', '10.2.0.0/24', '10.3.0.0/24']
for s in subs:
    n = ipaddress.IPv4Network(s)
    # RIPv1 无掩码,跨主类边界只能退回主类
    print('%-14s 报出去 -> 10.0.0.0/8' % s)

实跑输出:

--------------------------------------------------------------------
RIPv1 不带掩码会出什么事
--------------------------------------------------------------------
**RIPv1 的报文里没有掩码字段。**
**这意味着「它只能按 A 类、B 类、C 类的老规矩猜」。**
**在划了子网的网络里,这就出大事了。**

**假设一个公司有这三个子网**:**10.1.0.0/24、10.2.0.0/24、10.3.0.0/24。**

**RIPv1 会怎么报**:

  实际子网          网络号         RIPv1 报出去变成
  -------------------------------------------------------------
  `10.1.0.0/24`     `10.1.0.0`     **10.0.0.0/8**(整个 A 类)
  `10.2.0.0/24`     `10.2.0.0`     **10.0.0.0/8**(整个 A 类)
  `10.3.0.0/24`     `10.3.0.0`     **10.0.0.0/8**(整个 A 类)

**三条子网在 RIPv1 里被压成了一条 10.0.0.0/8。**
**对面那台路由器收到了,只知道「10 开头的东西在那边」**,**完全不知道里面还分了 .1、.2、.3。**
**所有发往 10.2.x.x 的包都往同一个方向走**——**如果对面也有 10 开头的网段,路由就彻底乱了。**

**这叫「有类路由」的局限**:**1980 年代网络还小,10 开头就是一个网,没人划子网。**
**等到大家都开始划子网,这个假设就崩了。**
**解决办法有两条**:
**一是「别在有类协议的网里划子网」(不现实);二是「给协议加上掩码字段」**——
**这就是 7.4.5 的 RIP2。**

**一个判据**:**抓包看到 RIP 报文里没有掩码,基本可以断定是 v1。**
**现在运行 v1 的网络极少,遇到基本是老旧设备。**

三条子网在跨主类边界时被压成了一条 10.0.0.0/8。 对面那台路由器收到了,只知道「10 开头的东西在那边」,完全不知道里面还分了 .1、.2、.3。 但要说清一个前提:这个汇总发生在「跨主类边界」的时候, 如果这三条都在同一个 10.0.0.0/8 内部互相通告,它们能靠接口掩码正确传过去(前提是掩码统一)。 所以准确的说法是「RIPv1 传不了跨主类的子网信息」,而不是「RIPv1 完全不懂子网」。 这个区别在排错时很关键: 如果「同一个楼里的子网互通没问题,跨专线就不通」,那就基本可以断定是自动汇总在捣鬼—— 而不是「子网配错了」。

30 秒实验

  1. 想一下:RIPv1 的报文为什么装不下掩码?(提示:看它的 20 字节怎么分的)
  2. 想一下:什么叫「不连续子网」,为什么它会出黑洞?
  3. 想一下:OSPF 的汇总和 RIPv1 的自动汇总,本质区别在哪?

常见误区

  1. 以为「RIPv1 完全不懂子网」。 同一主类网内部能传,靠接口掩码推断;出问题是在跨主类边界。
  2. 以为「自动汇总是可选的」。 RFC 1058 里是强制的,RIPv1 没得选。
  3. 以为「地址够用就不用规划」。 规划的目的是「能汇总」,不是「够不够用」。
自测三问(点开对答案) 1. RIPv1 为什么传不了子网掩码? —— **报文里根本没有掩码字段**,一条路由 20 字节里塞的是地址族、标记、地址、保留、度量。 2. 「不连续子网」为什么会出黑洞? —— **两边都报同一个主类网络,中间那台只能选一条**,另一半方向的流量就丢了。 3. 今天还需要注意汇总吗? —— **需要**,OSPF 和 BGP 都在汇总,汇总范围里混进不属于那边的地址就会黑洞。

下一节看 RIP 遇到「路断了」时怎么处理。

相关笔记