S32

路由原理

点击正文段落选定收藏或划线位置;未选定时使用屏幕内第一段。

课内目录

1 路由要解决的可达性问题

在 Linux 主机上,进程把日志写入本地文件时,需要文件路径帮助它找到对象;进程把日志发往远端时,需要目的 IP 地址帮助网络设备判断方向。但目的地址并没有附带完整行程。发送主机通常只知道先把包交给谁,沿途路由器再分别决定下一跳。路由解决的是:面对给定的目的地址,本设备应该从哪个接口继续发送,或明确报告没有可用路径。

设运维终端位于 192.0.2.0/24,实验服务器位于 198.51.100.0/24。这些是用于文档和实验的地址,实验时应放在隔离环境中。终端上的 shell 执行 ssh 198.51.100.20,启动的客户端进程提出通信请求;操作系统依据路由选择出口。即使终端能访问自己的网关,也不能据此推断它能访问服务器,因为后续设备可能没有目标网段的路由,服务器也可能没有返回终端的路径。

192.0.2.0/24 表示前 24 位是网络前缀。把地址范围写成前缀,是为了让路由表用少量记录表达多个地址的去向。这里的目的网段、下一跳和出接口是不同概念:目的网段描述“去哪里”,下一跳描述“先交给谁”,出接口描述“从本机哪里出去”。接口可以叫 eth0、ens3 或其他名称,命令中的接口名必须以实际环境为准。

主机与路由器逐跳决定去向
主机与路由器逐跳决定去向

同一链路上的目标通常由直连路由覆盖,不需要中间路由器代转;跨网段目标则常经网关发送。直连也不等于必然能通信,接口关闭、地址配置错误或邻居解析失败都可能阻止发送。路由只决定网络层的前进方向,不能替代链路状态检查,也不能保证目标进程正在监听端口。把这些条件分开,排查时才不会看到超时就修改默认路由。

本课默认讨论常见 IPv4 单播和普通目的地址路由。真实系统还可能按来源、策略或独立路由表选择路径,遇到这些配置应先确认上下文。本课先建立能够解释常见命令输出的模型:每台设备独立查表,每个方向独立成立,成功通信需要去程和回程都满足条件。

2 最长前缀匹配与转发表

考虑主机上的 3 条路由:0.0.0.0/0 via 192.0.2.1 dev eth0、198.51.100.0/24 via 192.0.2.2 dev eth0、198.51.100.128/25 via 192.0.2.3 dev eth0。访问 198.51.100.150 时,这 3 个前缀都能匹配。设备首先选匹配位数最多的前缀,因此选择 /25。访问 198.51.100.20 时不匹配这个 /25,但匹配 /24,于是交给 192.0.2.2。

这就是最长前缀匹配。“长”指前缀包含的固定位数更多,而不是命令文本更长,也不是下一跳离目标更近。/25 覆盖的范围比 /24 小,对该范围的描述更具体。默认路由 /0 没有固定的前缀位,可以匹配任意 IPv4 目的地址,通常充当没有更具体记录时的出口。默认路由并不证明网关知道全部目的地。

目的地址匹配的前缀选中的前缀下一跳
198.51.100.150/0、198.51.100.0/24、198.51.100.128/25198.51.100.128/25192.0.2.3
198.51.100.20/0、198.51.100.0/24198.51.100.0/24192.0.2.2
203.0.113.8/0/0192.0.2.1

路由上的 metric 常用来表达同类候选的优先程度,但不能把它理解为跨前缀竞争的总分。在本课的普通查表场景里,应先找最长匹配前缀,再理解该前缀下候选路径如何被系统选择。即使默认路由的 metric 更小,也不会因此压过能够匹配目标的 /24。同前缀候选的来源、优先级及等价路径规则可能因系统而异,需要结合实际配置判断。

从目的地址到选定出口的查表过程
从目的地址到选定出口的查表过程

转发表可以理解为数据包实际转发时使用的去向记录。管理命令显示的路由及其来源,有助于解释这些记录如何产生;实际发送还需要确认接口、下一跳是否可用。本课不展开内部数据结构。学习目标是拿到目的地址后,能说清命中了哪个前缀、为什么没有选默认路由,以及选定的出口与下一跳是什么。

还有 1 个容易混淆的细节:直连路由通常显示 dev eth0 而没有 via,表示目标所在网络直接连接在该接口上;经网关的路由则显示 via。不要给每条直连路由强行补网关。若网关本身无法通过可用链路到达,把它写入配置也不会自动创造通向它的连接。

3 控制面与数据面分离直觉

把网络看成持续运行的系统,会同时遇到“决定路径”和“按路径搬运数据”这 2 类工作。控制面负责形成、选择和更新可用路径,例如管理员添加静态路由,或路由进程从邻居处学习信息。数据面负责对经过的数据包执行查表、选择出口和转发等动作。这是职责划分,不要求它们必须运行在不同机器上。

可以把控制面比作维护目录的人,把数据面比作按目录投递的过程。目录更新后,后续投递才可能改变方向;目录错误时,执行过程即使完全按规则工作,也可能把包送向错误位置。因而“设备正在转发”与“路由信息正确”是不同证据。看到接口发送计数增长,只能说明有数据离开,不能证明目标收到,更不能证明回程成立。

在 Linux 中,ip route show 能查看当前上下文中的路由,ip route get 198.51.100.20 能查询本机会怎样处理这个目的地址。它们适合回答本机选择问题,却不负责展示整条网络路径。某个动态路由服务仍在运行,也不能单独证明目标前缀已经进入本机用于发送的路由表;需要把服务状态与具体前缀的结果对照。

控制信息变化后,相关设备可能在不同时间更新。某台设备已经改用新出口,邻居却仍按旧信息转发,这段过渡期可能出现绕行、丢包或短暂环路。这里先认识“变化需要传播与生效时间”即可,具体协议怎样检测故障、交换消息和计算路径,留到后续课程。不能假设保存配置后,全网会在同一瞬间获得完全一致的认识。

另外,主机能为自己的进程选择路由,并不表示它已经允许转发其他主机的数据。实验中让 Linux 充当路由器,还要确认 sysctl net.ipv4.ip_forward 的值,以及相关转发过滤规则。值为 0 时,本机访问两侧地址可能正常,跨越本机的通信仍然失败。观察时应先区分流量是本机产生、发给本机,还是经过本机转发,避免用错误的证据判断职责。

把职责落到 1 个以太网转发例子上:H 的地址为 192.0.2.10,经 R 访问 198.51.100.20。H 查表选定 R 后,需要通过 ARP 获得 R 在本链路上的 MAC 地址。发出的帧以 R 的 MAC 为目的,但帧内 IP 包的目的地址仍是服务器。网关只是下一段交付对象,不能把“下一跳地址”理解为替换 IP 目的地址。假设途中没有地址转换,源 IP 和目的 IP 会保持不变,而链路层地址会随着经过的以太网链路重新填写。

R 收到帧后,检查其中的 IP 包;若目的地址不是本机地址,就需要按转发路径处理。R 查询自己的转发表,找到服务器网段的出接口,再解析该接口上目标或下一跳的 MAC,重新封装后发送。转发还会使 TTL 递减,并更新 IPv4 首部校验和。因此在 R 两侧抓包时,可以用相同的源地址、目的地址和探测标识关联同一个包,同时预期看到链路层地址变化及 TTL 减少。若只按入口帧的目的 MAC 在出口寻找,可能误判包没有通过;若 TTL 已耗尽,则即使查表有结果,也不能继续转发。

这里存在 2 份用途不同的状态:路由表回答目的前缀应从哪里走,邻居表回答选定链路上的交付对象使用哪个 MAC。例如 R 的服务器网段路由仍在,但服务器断电,R 可能持续尝试解析服务器邻居,最后发送失败。此时路由记录存在与数据送达失败可以同时成立。反过来,邻居表中保留着网关的 MAC,也不能证明网关后面的目标前缀仍然可达。排查时应将查表结果与对应出接口上的邻居状态配对,不能用其中一份表代替另一份表。

再假设 H 同时有指向 R 的 /24 和指向另一网关的默认路由。R 停止回应 ARP 后,只要这条 /24 仍被选中,普通目的地址查表不会因为邻居解析失败就自动改走默认路由。故障检测与路径撤销需要额外机制,不能由“还有默认出口”推断已经具备备份能力。可以在隔离实验中停止网关接口,比较故障前后的路由查询、邻居状态和探测结果:若前缀选择未变而邻居失败,说明发送条件失效;只有相关路径被撤销或调整后,才应重新判断是否命中备用出口。

4 动手:跟踪一条路径的下一跳

准备隔离实验拓扑:客户端 H 的 eth0 是 192.0.2.10/24,路由器 R 的入口是 192.0.2.1/24,R 的另一侧连接服务器所在网络 198.51.100.0/24,服务器 S 是 198.51.100.20。H 经 R 访问 S,S 也需要拥有返回 192.0.2.0/24 的路由。若没有隔离环境,可以只运行查询命令;不要在远程管理所依赖的网络上随意改路由。

先在 H 上查看地址和链路,再查路由。这样能够区分“没有配置正确地址”与“地址正确但出口选择错误”。ip -br 用较紧凑的格式呈现接口,适合快速确定名称与状态。下面的命令都用于观察,不会新增路由。

ip -br link
ip -br addr
ip route show
ip route get 198.51.100.20
ip neigh show

假设查询返回 198.51.100.20 via 192.0.2.1 dev eth0 src 192.0.2.10。这表示本机计划经 eth0 把包交给 192.0.2.1,并为这次查询选择来源地址 192.0.2.10。它没有表示 R 已经收包。继续检查 ip neigh show,可看到接口上下一跳的邻居状态;若对应项持续为 FAILED,应检查链路、地址和网关是否确实在该链路上,而不是直接怀疑远端服务。

接着用探测命令建立不同层面的证据。ping -c 3 192.0.2.1 检查到网关的探测回应,ping -c 3 198.51.100.20 检查目标是否返回回应,traceroute -n 198.51.100.20 尝试显示沿途回应的设备。工具是否预装取决于系统;命令缺失是工具环境问题,不是网络故障。探测可能被过滤或限制,所以失败结果必须结合其他证据解释。

从本机查表到双向观测的证据顺序
从本机查表到双向观测的证据顺序

在具备抓包权限时,可在 H 上执行下面的有限次抓包,并从另一个终端发起探测。-n 避免名称解析干扰观察,-i 明确接口,-c 限制捕获数量。不要让抓包无限运行,也不要随意采集与实验无关的业务内容。

sudo tcpdump -ni eth0 -c 20 'arp or (icmp and host 198.51.100.20)'

如果 H 能看到请求离开但没有回复,应到 R 的入口和出口继续比对,最后在 S 上确认请求是否到达、回复选择哪个出口。每次只移动 1 个观察位置,记录时间、接口、源地址和目的地址。traceroute 中的 * 只表示相应探测未在等待时间内得到预期回应,不能直接解释为该位置禁止转发;后续跳仍有回应时,尤其应避免把这个符号当成故障定位结论。

5 静态路由与动态路由边界

静态路由由管理员或配置系统明确指定,适合路径少、边界清晰、变化不频繁的场景。例如隔离实验中,H 只需知道实验服务器网段应交给 R。在确认拓扑和权限后,可以用 sudo ip route add 198.51.100.0/24 via 192.0.2.1 dev eth0 添加这条记录。它表达了明确意图,但不会自动核实 R 后面是否仍能到达 S。

如果目标前缀已经存在,add 可能报告记录冲突;应先理解现有配置,不要把报错简单处理成“改用 replace”。替换可能覆盖原有去向,使管理连接中断。实验中新增的这条路由可以用 sudo ip route del 198.51.100.0/24 via 192.0.2.1 dev eth0 删除,但这个删除动作只适用于确认由本次实验添加的记录。若原来有路由,回滚必须恢复原值。

通过 ip route 做出的运行时变化,通常不会自动成为重启后的持久配置。发行版可能由网络管理服务或声明式文件管理地址和路由,后续重载也可能覆盖临时修改。因此要分别记录“当前正在使用什么”与“下次启动会生成什么”。持久化方法依环境选择,本课不把某个配置文件位置当成所有 Linux 系统的共同规则。

动态路由让设备交换可达性信息,并据此维护路径。它适合网络规模扩大、连接关系变化较多、需要自动响应故障的情况,但自动化不等于自动正确。错误发布的前缀可能传播到更多设备,过滤边界和变更检查仍然必要。动态路由也不能替代接口连通、地址规划和应用检查。后续学习 OSPF 与 BGP 时,会分别看到不同范围中的信息交换与路径选择。

选择静态或动态,不能只看路由条目数量,还要看变化频率、故障后允许的恢复时间、管理边界和团队维护能力。只有 2 个网段但经常切换出口,手工维护也可能出错;网段较多但连接固定,也不应仅凭数量就仓促引入协议。滑块展示的是教学情景下维护工作的变化,帮助表达取舍,不计算协议性能,也不提供真实网络的自动选型结论。

6 常见坑:非对称路由与黑洞

非对称路由指去程和回程经过不同路径。例如客户端请求从 R1 到服务器,服务器回复却从 R2 返回。只要两侧路径都有效且中间设备允许,通信可以正常完成,因此非对称本身不等于故障。但某些有状态过滤设备需要看到相互对应的双向流量,回包走其他路径时可能无法匹配状态而被丢弃。排查时应确认具体设备行为,不能把路径不同直接等同于违规。

这种问题的常见表现是:服务器抓包能看到请求,客户端却一直等待。此时只检查客户端的默认路由很容易走偏。应在服务器查询到客户端实际来源地址的路由,并抓取回复离开的接口。若进程监听正常,回复也已发出,就继续沿回程查找证据。多网卡主机还要关注选用的来源地址:发包的出口正确,不代表来源地址一定能从对端返回。

黑洞则描述数据进入某个方向后被丢弃,无法继续到达目标。它可能来自失效的下一跳、缺失的更具体路径,也可能来自显式丢弃路由。路由表里有目标前缀,仍可能发生黑洞,因为该记录只是本设备的决策,无法担保下一台设备具备正确路径。有些丢弃行为是为了明确网络边界而设计的,应结合预期判断,不能见到丢包就删除所有拒绝规则。

区分本机选路、邻居失败与回程缺失
区分本机选路、邻居失败与回程缺失

还要区分“没有路由”“邻居无法解析”“中间过滤”“服务没有回应”。这些故障可能都表现为应用超时,但对应动作完全不同。查表没有覆盖目标时,先补齐设计中的路径;下一跳邻居失败时,查直连链路;请求已到服务器时,查监听状态、服务日志和回程;探测被过滤时,用被允许的业务连接和双端观测补充判断。

错误的网络掩码也会制造误导。如果客户端把本应经网关到达的远端地址误认为直连,它可能在本地链路反复寻找目标邻居,而根本没有向预期网关发送。此时继续调整远端路由器不会解决问题。把 ip -br addr 与 ip route get 放在排查起点,就是为了尽早发现地址范围与路径假设不一致,而不是只盯着路由条目是否存在。

7 案例:错误汇总导致的环路

设 R1 面向分支,R2 面向上游。分支实际有 10.20.1.0/24 和 10.20.2.0/24,R1 却向 R2 提供了更宽的汇总 10.20.0.0/16。同时,R1 的默认路由指向 R2。访问真实分支地址时,R1 可以利用本地更具体的 /24 送达目标,因此日常抽查可能看不出异常;但汇总范围内还有许多没有实际网络承接的地址。

现在请求访问 10.20.99.8。R2 匹配 /16,把包交给 R1;R1 没有覆盖该目的地的分支明细,于是匹配默认路由,将包交回 R2。R2 再次匹配 /16。每台设备都严格执行了自己的表,组合起来却产生循环。错误不在最长前缀匹配算法,而在于 R2 相信 R1 能处理整个汇总范围,R1 又把其中未承接的地址送回上游。

包不会因此永久循环。IPv4 的 TTL 会在路由器转发时递减,到期后被丢弃,并可能产生超时报文。TTL 限制循环持续的时间,却没有修复错误去向。在允许回应的环境中,路径探测可能显示 R1、R2 重复出现;如果设备限制回应,也可能只看到部分重复或超时。不能只凭没有重复输出就排除环路,更不能通过调大 TTL 来解决路由错误。

修复应从汇总的责任范围开始。如果这里只需要发布实际存在的 2 个 /24,撤去过宽汇总并发布准确明细,可以收紧可达性声明。如果设计确实需要保留 /16,汇总发起处应对没有明细承接的范围采用明确的终止处理,例如经验证的丢弃路由,避免回落到指向上游的默认路由。正常分支明细依靠更长前缀继续转发,未承接地址则在边界终止。

后者会让不存在的目标不可达,这是明确表达设计边界;它不应掩盖本来应该存在、却意外丢失的分支路由。因此修复后要分别验证真实分支和空洞地址:前者保持通信,后者不再往返循环。还要检查明细消失时的行为是否符合预期,并监测丢弃是否异常增加。汇总减少条目,同时扩大了对外承诺的地址范围,不能只把它当成压缩路由表的技巧。

8 把路由变更写进变更窗口

路由变更影响的是正在运行的通信路径。写变更单时,先写清目的前缀、原下一跳、新下一跳、涉及的接口和设备,以及哪些来源会受到影响。“优化出口”不足以支持执行与复核;“将 H 到 198.51.100.0/24 的下一跳从 R1 改为 R2”才具有可检查的对象。还要说明这是运行时修改,还是同时更新负责持久化的配置来源。

变更前应留存地址、路由、相关规则及关键连接的基线。在普通 Linux 环境中,可把 ip -br addr、ip route show、ip rule show 的结果重定向到按时间命名的文件,并记录当前网络上下文。ip rule show 用来发现是否存在额外策略;如果有多张表或隔离网络环境,就不能直接把普通主表查询当成全部事实。基线文件应限制访问,避免泄露内部网络结构。

执行顺序应考虑过渡期间的双向可达。通常需要先确认新路径上的设备已经具备所需去向和回程,再切换入口流量,但具体顺序应由拓扑决定。逐台修改后停下来验证,不要同时在多个终端替换相互依赖的路由。若操作通过即将被修改的路径进行,应事先准备可用的控制台或独立管理通道,避免连接断开后失去恢复能力。

验证不能只写“ping 正常”。至少明确测试来源、目的地址、预期下一跳、实际业务探测和可接受的丢包或延迟范围。对于服务器,还可以用 ss -lnt 核对监听状态,通过已有业务健康检查确认连接。路由切换后,既要检查新建连接,也要关注已有连接是否受影响;不能用某次成功回应覆盖所有会话的表现。

回滚条目要写出恢复的具体值和触发条件,例如目标业务持续不可达、回程不符合设计或管理连接受影响时,恢复此前的路由与配置。删除新路由是否足够,取决于原来是否已有记录;执行过替换,就必须恢复原记录。窗口结束前还要核对持久配置与运行状态,避免现场测试成功,却在网络服务重载或主机重启后回到错误路径。

9 从路由基础走向 OSPF/BGP(S33)

到这里,可以把路由问题拆成连续的判断:目标属于哪个范围,本机匹配哪个前缀,下一跳是否能在本链路到达,后续设备是否承接该范围,回复是否有路可走。这个顺序把本机证据与全程结论分开,也把路径选择与服务状态分开。应用报错只是调查入口,真正定位需要把命令输出放回具体设备、方向和时间点。

静态路由让管理员直接维护去向;动态路由则让设备根据交换的信息维护去向。两者最终都必须落实为设备能够执行的转发决策,因此最长前缀、默认路由、回程和汇总边界不会在学习协议后失效。协议运行正常,也仍然可能发布错误范围;前缀已经学到,也仍然可能遇到过滤或邻居故障。基础观测能够帮助判断问题位于信息形成还是实际发送过程。

下一课 S33 将讨论 OSPF 与 BGP。先保留范围直觉:OSPF 常用于同一管理域内的路由协作,BGP 常用于不同管理边界之间交换可达性,也有其他部署方式。这里不提前背消息类型、状态迁移或路径属性。进入下一课时,可以带着问题学习:信息从哪里来,谁有权发布,如何选择候选,撤回信息后设备如何改变路径。

对 shell 和自动化脚本而言,还要记住命令成功退出只证明命令按其接口约定完成,不等于网络目标已经达成。脚本添加路由后应查询目标的实际选路,再执行约定的通信检查,并保留失败输出。网络错误与文件错误一样需要上下文:明确设备、接口、目标、操作时间和预期,才能让其他值班人员复现判断,而不是反复尝试同一条命令。

放进方案里

为实验室管理网访问服务器网编写方案时,先定义通信矩阵:哪些来源需要访问哪些目的前缀和端口,哪些方向无需开放。列出客户端、路由设备、服务器的接口地址与管理入口,标明每段链路的前缀。方案要同时画出去程和回程,并说明服务器回复管理终端时使用的下一跳,不能只画请求到达服务器的箭头。

将路由记录写成可核对的清单,包含目的前缀、下一跳、出接口、配置来源和负责维护的角色。小规模固定环境可以采用静态路由,但应说明链路失效时由谁发现、如何恢复,以及临时命令怎样转成持久配置。需要动态学习时,先写清管理边界与允许交换的前缀,协议细节由后续设计补足,不用“自动收敛”代替可验证的恢复目标。

验收应覆盖正常目标、无承接地址和返回方向。正常目标需要查表结果符合设计,并完成实际管理连接;无承接地址应在预定边界终止,不能在默认路由与汇总之间循环。发生超时时,按本机选路、邻居状态、入口出口观测、目标监听、回程查表的顺序收集证据。探测工具被过滤时,补充允许的业务检查,避免以单次探测代替验收。

变更附件应保存实施前后的配置差异、执行顺序、观察窗口与回滚值。为远程操作准备独立恢复入口,并定义何种不可达或业务异常触发回滚。结束时确认运行路由与持久配置一致,记录未覆盖的来源或网络上下文。方案最终应让接班人员能够回答:谁声明可达、谁执行转发、哪里验证结果、失败后恢复到什么状态。

10 小结:下一步 OSPF 与 BGP(S33)

路由通过逐跳决策连接不同网络。最长前缀匹配决定具体去向,默认路由提供兜底;控制面维护路径信息,数据面执行转发。检查通信时,要把本机查表、下一跳可达、沿途承接和回程成立分别验证。

可以用 3 个问题自测:为什么 /24 能压过 metric 更小的 /0?为什么服务器收到请求仍可能让客户端超时?为什么汇总与默认路由可能形成循环?能结合命令和拓扑回答后,再进入 S33,学习 OSPF 与 BGP 如何交换与选择路由信息。

同阶段相关课

AI 答疑

默认关闭。启用后,只发送本课标题、最近阅读的屏幕内正文摘录(最多 6000 字)与本次问题。

配置自己的服务