路由选择协议
路由选择协议
一个问题:路由器怎么知道路
假设全球有 10 万台路由器,每台连着几个网络。路由器 A 知道它的直连网络是 X、Y、Z,但它不知道北京的用户怎么去纽约。这件事没有人能预先知道——网络拓扑一直在变(新运营商上线、链路故障、设备维护)。
如果让你设计一套机制让全球路由器能"互相学习"到达信息,你会怎么设计?
这是路由协议要解决的核心问题。从 1980 年代开始,网络工程师们想了 3 种主流方案:
- 距离向量(RIP):每台路由器告诉邻居"我能到哪些网,距离多少"
- 链路状态(OSPF):每台路由器告诉所有人"我连了哪些邻居,链路开销多少"
- 路径向量(BGP):每台路由器告诉邻居"我能到这些 AS,沿途经过哪些 AS"
每种方案都对应真实需求场景。下面逐个讲。
距离向量:最简单的想法
原理:每台路由器维护一张表,记录"去每个网络要多少跳"。每隔 30 秒把整张表广播给直接相连的邻居。邻居收到后,把自己的表项 + 1,再广播给它们的邻居。Bellman-Ford 算法是这个思想的标准实现。
最经典的协议:RIP(Routing Information Protocol)。RIP 用"跳数"作为距离度量,最多 15 跳。16 跳就认为不可达。
RIP 的工作过程:
- 路由器启动时只知道直连网络(距离 0)
- 每 30 秒向邻居广播整张路由表
- 邻居收到后:邻居去某网络 X 的距离 = 我去邻居的距离 + 邻居去 X 的距离
- 如果我的表里没有 X,或新路径更短,更新我的表
- 持续这个过程直到收敛(所有路由器的表稳定)
RIP 的致命缺陷:慢收敛 + 路由环路。
设想一个网络突然断了。路由器 C 原本通过 B 到达网络 X(跳数 3)。C 还以为通过 D 也能到 X(跳数 5),但其实 D 也是通过 B 间接知道的。如果 B 现在告诉 C "我到不了 X 了",C 一开始不信,会在跳数飙升到 16 之前继续用旧路径一段时间。这个过程中包会绕圈子。
解决环路的方法:水平分割、毒性逆转、触发更新。但都是补丁。RIP 已经被 OSPF 全面取代。
链路状态:现代企业网的选择
原理:每台路由器向全网(不是邻居)洪泛自己的"链路状态"——我连了哪些邻居,链路开销多少。每台路由器收到所有路由器的链路状态后,在内存里重建出完整的网络拓扑图,然后用 Dijkstra 算法算出自己到所有网络的最短路径。
最经典的协议:OSPF(Open Shortest Path First)。OSPF 是互联网内部网关协议(IGP)的事实标准。
OSPF 的工作过程:
- 发现邻居:路由器启动时向所有 OSPF 接口发 Hello 包,相邻路由器互相认识,建立邻居关系。
- 交换链路状态:邻居之间交换 LSA(Link State Advertisement),每条 LSA 描述"我有这几个接口,每个接口连着谁,开销多少"。
- LSDB 同步:每台路由器把收到的所有 LSA 存到 LSDB(Link State Database)。同一个区域(area)里所有路由器的 LSDB 是一样的。
- 算最短路径:用 Dijkstra 算法,根据 LSDB 算出到自己为根的最短路径树,生成路由表。
OSPF 的关键设计:分层(area)。
大型企业网有几万台路由器,如果所有路由器 LSDB 都一样,LSA 洪泛会很慢。OSPF 引入了区域(area)概念:
- 骨干区域 area 0:所有非骨干区域必须连到骨干区域
- 普通区域:只和骨干区域交换汇总路由
- 区域间路由汇总:减少 LSA 数量
这让一个 10000 台路由器的网络拆成 100 个 area,每个 area 100 台,规模大幅压缩。
OSPF 用"开销"做度量,可以基于带宽计算(百兆链路开销 1,万兆链路开销更小),让流量走更快的链路而不是跳数最少的链路。
OSPF 的优势:
- 收敛快(秒级)——LSA 触发更新,故障几秒内全网知道
- 无环路——每台路由器算的是完整拓扑
- 分层——大型网络可扩展
OSPF 的劣势:
- CPU 和内存消耗大——LSDB 大,Dijkstra 计算开销大
- 配置复杂——需要规划 area、设计 cost、配置认证
路径向量:互联网黏合剂
原理:BGP(Border Gateway Protocol)和前面两个协议都不同。BGP 不是算最短路径,而是应用策略——管理员手动配置"我愿意把哪些网络告诉邻居,邻居愿意把哪些网络告诉我"。
BGP 的核心概念:AS(自治系统)。
每个 ISP、大公司、机构都有自己独立的 AS 号。比如:
- 中国电信 AS 4134
- 中国移动 AS 9808
- 阿里云 AS 37963
- Cloudflare AS 13335
一个 AS 是"单一管理下的一组路由器和网络"。BGP 是 AS 之间的协议,不同 AS 边界上的路由器会建立 BGP 连接交换路由。
BGP 路由 = 网络前缀 + AS 路径。
例如一条 BGP 路由:8.8.8.0/24 AS path: 15169 6453 6453 6453
意思是:要到达 8.8.8.0/24,沿途经过 AS 15169(Google)、3 个 AS 6453(tata communications)。AS 路径是"路径向量",记录了完整路径。
BGP 决策的复杂过程:
当一个 BGP 路由器收到多条去同一目的的路由时,按顺序比较:
- Weight(Cisco 私有,本地有效)
- Local Preference(本 AS 内部一致)
- Locally Originated(自己产生的优先)
- AS Path Length(AS 路径短的优先)
- Origin(IGP > EGP > Incomplete)
- MED(多出口区分器,对端 AS 传过来的偏好)
- eBGP > iBGP(外部 BGP 比内部优先)
- IGP Metric(到达 BGP 邻居的 IGP 开销)
- Router ID(最后看路由器 ID 大小)
这套决策过程让 BGP 极其灵活——运营商可以"我虽然能到 X,但我不告诉你去 X 的路径","我虽然能到 X,但我更愿意走 Y","我虽然能到 X,但拒绝给竞争对手转发到 X 的流量"。BGP 是互联网政策的体现。
BGP 的真实事件:
- 2008 年巴基斯坦封 YouTube 事件:巴基斯坦电信工程师想在国内封 YouTube,配置 BGP 路由时误把 YouTube 的前缀发到全球,导致全球流量涌向巴基斯坦电信,YouTube 全球宕机 2 小时。
- 2017 年 Google 误配置:Google 工程师把一条 BGP 路由打错前缀长度(写成 /25 实际是 /20),导致日本 30 分钟访问不了 Google。
- 2018 年 AWS DNS 大故障:AWS DNS 服务 BGP 通告故障,整个 Route53 在美国东部宕机 4 小时。
路由协议的对比
| 协议 | 类型 | 适用规模 | 收敛速度 | 复杂度 |
|---|---|---|---|---|
| RIP | 距离向量 | < 50 路由器 | 慢(分钟级) | 低 |
| OSPF | 链路状态 | < 1000 路由器 | 快(秒级) | 中 |
| IS-IS | 链路状态 | 运营商骨干 | 快 | 中 |
| BGP | 路径向量 | 互联网 | 慢(分钟) | 高 |
选型原则:
- 小企业(< 10 台路由器):静态路由 + 缺省路由
- 中型企业(10-100 台):OSPF 单区域
- 大型企业(100-1000 台):OSPF 多区域
- 运营商骨干:IS-IS 或 OSPF
- 不同 AS 之间:BGP 唯一选择
真实场景:用 traceroute 看到的 AS 路径
traceroute -A 8.8.8.8(Linux,-A 显示 AS 号):
1. 192.168.1.1 [AS 9808] 2ms
2. 10.0.0.1 [AS 9808] 5ms
3. 202.97.10.65 [AS 4134] 15ms ← 中国电信骨干入口
4. 202.97.33.46 [AS 4134] 38ms
5. 72.14.215.85 [AS 15169] 42ms ← Google AS
6. 93.184.216.34 [AS 15169] 43ms包从家庭路由器(AS 9808,中国移动家庭网关)→ 中国电信骨干(AS 4134)→ Google(AS 15169)。三个 AS 把一个包从北京送到 Mountain View。
思考题
- RIP 用跳数做度量,最大的问题是它认为"跳数少"就是"路径好"。但一个 3 跳的 56Kbps 链路真的比 1 跳的 100Mbps 链路好吗?怎么改进?
- OSPF 路由器算最短路径需要完整网络拓扑。如果网络里有 10000 台路由器,OSPF 还能用吗?为什么?需要怎么改造?
- BGP 用 AS 路径防环路(看到自己的 AS 号在路径里就丢弃)。但 eBGP 和 iBGP 是怎么保证路由不环的?
- 你在云厂商的 VPC 里看到路由表里既有"系统路由"也有"自定义路由"。系统路由通常是哪些?自定义路由会覆盖系统路由吗?
延伸阅读
- 《深入浅出计算机网络》(高军)第 4 章
- 《TCP/IP 详解 卷 1:协议》(Stevens)
- RFC 2328: OSPF Version 2
- RFC 4271: A Border Gateway Protocol 4 (BGP-4)
- 动手实验:在 Linux 装
bird或quagga,模拟运行 OSPF - 动手实验:访问 bgp.tools 看全球 AS 拓扑