1. 为什么还要死磕 OSPF 这个老协议
刚入行那会儿,带我的师傅扔给我一本协议手册,说“把 OSPF 啃下来,以后园区网、数据中心、广域网的路由你都能摸个七七八八”。当时我不信,觉得这玩意儿又老又枯燥,满屏的 LSA、区域、DR/BDR,看着就头大。结果干了几年项目才发现,不管是企业总部和分支互联,还是园区核心到接入的三层打通,甚至一些云上专线的混合组网,OSPF 出现的频率高得离谱。你可以说它不新潮,但你不能说它不重要。
这篇文章我想干一件事:把 OSPF 协议基础从头到尾捋一遍,不是照本宣科念 RFC,而是站在一个真正配过、排过障、踩过坑的从业者角度,把那些“书上不写、但现场必须知道”的东西讲清楚。核心关键词就是OSPF 协议基础,围绕它的邻居建立、区域划分、LSA 类型、路由计算、开销选路这些核心机制展开。适合谁看?刚接触网络工程、准备考认证的初学者,以及配过 OSPF 但一直没搞明白“为什么这么配”的运维同学。看完你至少能做到:独立规划一个多区域 OSPF 网络,看懂邻居卡在哪个状态,知道改哪个参数能影响选路。
我尽量说人话,复杂的地方用生活类比,能上表格就上表格,能贴配置就贴配置。所有参数和步骤都基于通用网络设备的常见实践,不同厂商命令略有差异,但原理完全一致。
2. OSPF 到底是个什么东西:先建立直觉再谈细节
2.1 用“快递网点”类比 OSPF 的工作方式
OSPF 全称是开放式最短路径优先,本质是一种链路状态路由协议。什么叫链路状态?你可以把整个网络想象成一张快递网点地图。每个网点(路由器)只负责搞清楚一件事:我直连了哪些邻居网点,到它们的“运费”(开销)是多少。然后每个网点把这份“本地情报”打包成一份公告,发给同一片区(区域)里的所有其他网点。最终每个网点手里都攒齐了全片区的公告,自己拼出一张完整地图,再用最短路径算法算出到每个目的地的最优路线。
这个“拼地图再算路”的模式,和距离矢量协议(比如 RIP)有本质区别。RIP 是邻居之间互相喊“我到某地要 3 跳”,信息是二手甚至三手的,容易传错、收敛慢。OSPF 是每个人都拿到一手情报自己算,所以收敛快、无环路、支持大规模网络。代价就是它更吃内存和 CPU,因为每台路由器都要存整张地图。
2.2 三个必须刻进脑子里的核心概念
第一个是区域(Area)。OSPF 把大网络切成一个个区域,区域用数字标识,骨干区域固定是 0。为什么切?因为不切的话,每台路由器都要存全网地图,网络一大就撑不住。切了区域之后,区域内的路由器只需要存本区域的详细地图,跨区域的信息由区域边界路由器做汇总。这就像全国快递网络分成华东、华北几个大区,区内网点记区内详细路线,跨区只记大区之间的干线。
第二个是路由器角色。同一台路由器在不同场景下身份不同:内部路由器所有接口都在一个区域;骨干路由器至少有一个接口在区域 0;**区域边界路由器(ABR)**同时连接骨干区域和普通区域,负责区域间路由汇总;**自治系统边界路由器(ASBR)**负责把外部路由(比如静态路由、其他协议的路由)引入 OSPF。搞清楚角色,才能看懂 LSA 是谁发的、发给谁。
第三个是链路状态数据库(LSDB)。这是 OSPF 的“地图仓库”。同一个区域内所有路由器的 LSDB 必须完全一致,这是 OSPF 正常工作的前提。如果两台路由器 LSDB 不一致,说明有 LSA 没同步到,路由计算就会出问题。排查 OSPF 故障时,对比 LSDB 是最有效的手段之一。
2.3 OSPF 的五种报文,各司其职
OSPF 靠五种报文完成所有交互,理解它们就理解了 OSPF 的“语言体系”。
| 报文类型 | 名称 | 作用 | 生活类比 |
|---|---|---|---|
| Type 1 | Hello | 发现邻居、维持邻居关系、选举 DR/BDR | 打招呼、确认对方还在线 |
| Type 2 | DBD | 描述本地 LSDB 摘要,协商同步 | 交换各自地图目录 |
| Type 3 | LSR | 请求缺失的 LSA | 我要你目录里那份详细资料 |
| Type 4 | LSU | 发送完整的 LSA | 把详细资料寄过去 |
| Type 5 | LSAck | 确认收到 LSA | 签收确认 |
Hello 报文是重中之重,它里面携带了一堆参数,这些参数必须双方一致才能建立邻居。我见过太多“邻居起不来”的案例,最后查出来就是 Hello 里的某个参数对不上。具体哪些参数,后面专门讲。
3. 邻居建立全过程:从陌生到“全邻接”的七个状态
3.1 七个状态逐个拆解
OSPF 邻居建立不是一步到位的,它要经历七个状态,每个状态卡住都对应不同的问题。这是排查故障的核心线索,必须背下来。
Down:初始状态,还没收到对方的 Hello。如果一直停在 Down,说明物理链路、接口状态、或者 Hello 根本没发出去。
Init:收到了对方的 Hello,但对方发来的 Hello 里没有列出我的 Router ID。这说明单向通信——我能收到它的,它收不到我的。常见原因是单向链路、ACL 拦截、或者组播被过滤。
2-Way:双方 Hello 里都看到了对方,双向通信正常。这是邻居关系建立的最低门槛。在广播网络中,非 DR/BDR 的路由器之间会停在这个状态,这是正常的,不用管。
ExStart:开始协商主从关系,决定谁先发 DBD。这个状态卡住通常是MTU 不匹配,因为 DBD 报文大小受 MTU 影响。我踩过这个坑,两台设备一个 MTU 1500 一个 1400,邻居死活卡在 ExStart,改一致后秒过。
Exchange:互相交换 DBD 摘要,告诉对方自己有哪些 LSA。
Loading:根据 DBD 摘要,用 LSR 请求自己缺失的 LSA,对方用 LSU 回应。
Full:LSDB 完全同步,邻接关系建立完成。只有 Full 状态的路由器之间才会互相计算路由。
3.2 Hello 报文里必须一致的参数
邻居能不能建起来,Hello 报文里的这些字段必须双方一致,任何一个不匹配都会卡在 Init 或 2-Way:
- Hello Interval:默认广播网络 10 秒,NBMA 网络 30 秒。
- Dead Interval:默认是 Hello 的 4 倍,即 40 秒或 120 秒。超过这个时间没收到 Hello,邻居就被判定失效。
- 区域 ID:必须在同一区域,否则直接不认。
- 认证类型和密钥:认证不通过,Hello 直接被丢弃。
- Stub 区域标志:一边是 Stub 一边是普通区域,邻居起不来。
- 网络掩码:在广播网络中必须一致(点对点网络不检查)。
实操心得:调 Hello 和 Dead 时间时,一定要两端同时改。只改一端,Dead 时间不一致,邻居会反复震荡,日志里全是“Neighbor down”的告警,特别容易被误判成链路闪断。
3.3 DR 和 BDR 选举:广播网络里的“班长”机制
在以太网这种广播网络里,如果 N 台路由器两两建立 Full 邻接,会有 N×(N-1)/2 个邻接关系,LSA 泛洪量爆炸。OSPF 的解决办法是选一个DR(指定路由器)和一个BDR(备份指定路由器),所有其他路由器(DROther)只和 DR/BDR 建立 Full 邻接,DROther 之间停在 2-Way。
选举规则很简单:先比接口的DR 优先级(默认 1,范围 0-255,0 表示不参与),优先级高的赢;优先级相同比Router ID,大的赢。Router ID 是 OSPF 里路由器的唯一标识,通常取环回口地址或手动指定。
这里有个大坑:DR 选举不是抢占的。也就是说,如果 DR 已经选出来了,后来一台优先级更高的路由器加入,它不会抢走 DR 位置,除非 DR 失效重新选举。所以规划时要么提前设好优先级,要么重启 OSPF 进程让它重新选。
注意:优先级为 0 的接口永远不会成为 DR/BDR,适合那些你不想让它参与选举的场景,比如某些服务器对接的接口。
4. 区域划分与 LSA 类型:OSPF 的“信息分层”艺术
4.1 为什么要划分区域,怎么划才合理
单区域 OSPF 在小型网络里没问题,但网络一大,每台路由器都要存全网 LSDB,还要在拓扑变化时全网重新计算,CPU 和内存压力巨大。划分区域的核心目的就是把拓扑变化的影响限制在区域内,区域内的震荡不会波及整个网络。
划分原则我总结了几条实战经验:
- 区域 0 必须是连续的,所有非骨干区域都要直接或间接连到区域 0。如果物理上连不上,要用虚链路(Virtual Link)打通,但虚链路是补救手段,能不用就不用,它增加复杂度还不好排障。
- 区域规模控制在合理范围,一般建议一个区域内的路由器不超过 50 台,具体看设备性能和网络稳定性。区域太大,SPF 计算频繁,收敛变慢。
- 按地理或功能划分,比如总部一个区域、每个分支一个区域、数据中心单独一个区域。这样某个分支震荡不影响其他分支。
- ABR 是区域间的咽喉,它维护多个区域的 LSDB,负责把区域内的路由汇总后通告到其他区域。ABR 性能要留足余量。
4.2 六种常见 LSA 类型,谁发谁收要分清
LSA 是 OSPF 传递信息的载体,不同类型承载不同信息,传播范围也不同。这是 OSPF 最核心也最容易搞混的部分,我用表格理清楚。
| LSA 类型 | 名称 | 谁产生 | 传播范围 | 携带信息 |
|---|---|---|---|---|
| Type 1 | Router LSA | 每台路由器 | 本区域内 | 本路由器的接口、链路、开销 |
| Type 2 | Network LSA | DR | 本区域内 | 广播网段的子网掩码和连接的路由器 |
| Type 3 | Summary LSA | ABR | 区域间 | 把一个区域的路由汇总通告到其他区域 |
| Type 4 | ASBR Summary LSA | ABR | 区域间 | 告诉其他区域 ASBR 的位置 |
| Type 5 | AS External LSA | ASBR | 全 OSPF 域 | 外部引入的路由 |
| Type 7 | NSSA External LSA | ASBR | NSSA 区域内 | NSSA 区域内的外部路由 |
理解这张表的关键是记住“谁产生、传多远”。Type 1 和 Type 2 是区域内的“本地新闻”,出不了区域。Type 3 和 Type 4 是 ABR 做的“跨区简报”。Type 5 是 ASBR 从外面带进来的“国际新闻”,全网传播。Type 7 是 NSSA 区域特有的,因为 NSSA 不允许 Type 5 进入,所以用 Type 7 在区域内传,到了 ABR 再转成 Type 5 发出去。
4.3 特殊区域:Stub、Totally Stub、NSSA 怎么选
特殊区域的目的是减少区域内的 LSA 数量,减轻边缘路由器负担。选哪种取决于你的网络需求。
Stub 区域:不允许 Type 5 LSA 进入,ABR 会自动下发一条默认路由(Type 3)指向自己。适合那些只有一条出口、不需要知道外部详细路由的分支区域。
Totally Stub 区域:在 Stub 基础上,连 Type 3 LSA 也不允许进入(除了默认路由),区域内的路由器只知道一条默认路由。最省资源,但灵活性最差。
NSSA(Not-So-Stubby Area):不允许 Type 5 进入,但允许区域内有 ASBR 引入外部路由,用 Type 7 承载。适合那些既想减少外部 LSA,又需要自己引入少量外部路由的区域。
选择逻辑很简单:分支区域完全不需要外部路由细节,用 Stub;连区域间路由细节都不需要,用 Totally Stub;需要自己引入外部路由,用 NSSA。
踩坑记录:配置 Stub 区域时,区域内所有路由器都必须配成 Stub,只要有一台没配,邻居就起不来。我见过因为漏配一台接入交换机导致整个区域 OSPF 瘫痪的案例,排查了半天才发现是区域标志不一致。
5. 路由计算与开销选路:OSPF 怎么选出最优路径
5.1 SPF 算法到底在算什么
OSPF 用 Dijkstra 最短路径优先算法计算路由。每台路由器以自己为根,根据 LSDB 里的链路状态信息,算出一棵到区域内所有目的地的最短路径树。这个过程叫 SPF 计算。
SPF 计算分两步:第一步算区域内路由,基于 Type 1 和 Type 2 LSA,这是最精确的。第二步算区域间路由,基于 Type 3 LSA,ABR 会告诉你有条路能到某个网段,开销是多少。外部路由(Type 5/7)则是在此基础上再叠加。
关键点:SPF 计算是独立的,每台路由器各算各的,但因为有统一的 LSDB,算出来的结果一致,不会出现环路。这也是链路状态协议比距离矢量协议优越的地方。
5.2 开销(Cost)怎么算,怎么改
OSPF 选路的唯一依据就是开销,开销越小越优先。开销的计算公式是:
接口开销 = 参考带宽 / 接口带宽参考带宽默认是 100 Mbps。也就是说,一个 100M 接口开销是 1,一个 10M 接口开销是 10,一个 1000M 接口开销是 0.1,但 OSPF 开销取整,最小为 1,所以千兆和百兆接口开销都是 1。这在千兆、万兆普及的今天明显不合理——万兆和百兆算出来一样,选路就乱套了。
解决办法是修改参考带宽。比如把参考带宽改成 10000 Mbps(10G),那么万兆接口开销是 1,千兆是 10,百兆是 100,区分度就出来了。修改命令通常是auto-cost reference-bandwidth 10000,注意全网所有路由器都要改成一样的值,否则开销计算标准不统一,选路会出问题。
除了改参考带宽,也可以手动指定接口开销,命令类似ip ospf cost 10。手动指定优先级最高,适合需要精确控制选路的场景。比如你有两条路径,一条走专线一条走互联网,想让专线优先,就把互联网接口开销调大。
5.3 等价路由与负载均衡
如果到同一目的地有多条开销完全相同的路径,OSPF 会把这些路径都放进路由表,实现等价多路径负载均衡(ECMP)。默认情况下,很多设备支持 4 条或 8 条等价路径,具体看设备能力。
这个特性在数据中心和核心层非常有用,可以充分利用带宽。但要注意:等价路由要求开销完全相等,差一点都不行。所以规划时要精确计算,必要时手动调开销让它们相等。
实操心得:ECMP 虽然好,但排查问题时会变复杂,因为流量可能走不同路径,抓包和定位故障点要考虑多条路径。我一般会在核心层用 ECMP,接入层保持单路径,降低排障难度。
6. 实操配置:从零搭一个多区域 OSPF 网络
6.1 场景描述与拓扑规划
假设一个典型的企业网络:总部为核心区域(Area 0),有两个分支分别划为 Area 1 和 Area 2。总部有一台核心路由器作为 ABR,连接两个分支。分支各有一台路由器,下挂业务网段。另外总部通过一台 ASBR 引入一条静态路由作为外部路由,验证 Type 5 LSA 的传播。
拓扑逻辑如下:
- 核心路由器 R1:连接 Area 0 和 Area 1,是 ABR。
- 分支路由器 R2:在 Area 1,下挂 192.168.10.0/24 网段。
- 分支路由器 R3:在 Area 2,下挂 192.168.20.0/24 网段。
- 边界路由器 R4:作为 ASBR,引入外部路由 10.0.0.0/24。
6.2 基础配置步骤
第一步,配置接口 IP 和环回口。环回口用于稳定 Router ID,建议每台路由器都配一个。
# R1 配置示例 interface Loopback0 ip address 1.1.1.1 255.255.255.255 interface GigabitEthernet0/0 ip address 10.1.1.1 255.255.255.0 interface GigabitEthernet0/1 ip address 10.1.2.1 255.255.255.0第二步,启用 OSPF 进程并宣告网段。注意宣告时要写对区域。
# R1 启用 OSPF,Router ID 手动指定为 1.1.1.1 router ospf 1 router-id 1.1.1.1 network 10.1.1.0 0.0.0.255 area 0 network 10.1.2.0 0.0.0.255 area 1 network 1.1.1.1 0.0.0.0 area 0第三步,分支路由器类似配置,注意区域号对应。
# R2 配置,属于 Area 1 router ospf 1 router-id 2.2.2.2 network 10.1.2.0 0.0.0.255 area 1 network 192.168.10.0 0.0.0.255 area 1 network 2.2.2.2 0.0.0.0 area 16.3 验证邻居和路由
配置完成后,第一件事是查邻居状态。
show ip ospf neighbor正常应该看到邻居状态是Full。如果卡在 ExStart,查 MTU;卡在 Init,查单向通信;卡在 2-Way 且对方是 DROther,那是正常的。
第二件事是查 LSDB,确认 LSA 同步。
show ip ospf database在 R2 上应该能看到 Type 1、Type 2(如果有广播网段)、Type 3(ABR 下发的区域间路由)。如果 R4 引入了外部路由,还能看到 Type 5。
第三件事是查路由表,确认路由计算正确。
show ip route ospfR2 应该能学到 192.168.20.0/24(Area 2 的网段)和 10.0.0.0/24(外部路由),下一跳指向 R1。
6.4 引入外部路由与验证
在 R4 上配置静态路由并引入 OSPF:
ip route 10.0.0.0 255.255.255.0 Null0 router ospf 1 redistribute static subnetssubnets关键字很重要,不加的话只引入主类网络,子网路由会被丢弃。引入后,R2 和 R3 应该都能学到 10.0.0.0/24,并且能看到 Type 5 LSA。
注意:引入外部路由时,建议配合路由策略(route-map)做过滤,避免把不该引入的路由带进 OSPF。生产环境里我见过因为 redistribute 没加过滤,把一条默认路由引入导致全网流量异常的案例。
7. 常见故障排查:邻居起不来、路由学不到怎么办
7.1 邻居状态卡壳速查表
| 卡住状态 | 最可能原因 | 排查方法 |
|---|---|---|
| Down | 物理链路断、接口未启用、Hello 未发送 | 查接口状态、查 ACL、抓包看 Hello |
| Init | 单向通信、ACL 拦截、组播过滤 | 双向抓包、检查 ACL 和组播配置 |
| 2-Way | 广播网络中正常(DROther 之间) | 确认是否应该建立 Full,检查 DR 选举 |
| ExStart | MTU 不匹配、Router ID 冲突 | 查接口 MTU、查 Router ID 唯一性 |
| Exchange | DBD 报文异常、LSDB 过大 | 查日志、查 LSDB 数量 |
| Loading | LSA 请求无响应、链路不稳定 | 查 LSR/LSU 交互、查链路质量 |
7.2 路由学不到的排查思路
如果邻居是 Full 但路由学不到,按这个顺序查:
第一,查 LSDB 是否一致。在两端分别show ip ospf database,对比 LSA 数量和内容。如果不一致,说明 LSA 同步有问题,可能是 MTU 或链路问题。
第二,查区域配置。确认两端接口是否在同一区域,区域类型(Stub/NSSA)是否一致。
第三,查网络类型。OSPF 接口网络类型(广播、点对点、NBMA)必须匹配,否则 Hello 和 LSA 交互会异常。常见的是两端一个广播一个点对点,邻居能起来但路由学不到。
第四,查过滤策略。有没有在 OSPF 进程里配 distribute-list 或 route-map 过滤了路由。
第五,查路由汇总。ABR 上如果配了区域间汇总,可能把明细路由汇总掉了,导致某些网段学不到。
7.3 几个我踩过的真实坑
坑一:Router ID 冲突。两台路由器 Router ID 一样,邻居能起来但 LSDB 混乱,路由时有时无。排查时用show ip ospf看 Router ID,确保全网唯一。建议手动指定 Router ID,不要依赖自动选举。
坑二:MTU 不匹配。前面提过,卡在 ExStart。这个坑隐蔽在于 ping 大包能通(因为分片),但 OSPF DBD 不分片,直接卡住。解决办法是两端 MTU 一致,或者在接口上配ip ospf mtu-ignore(不推荐,治标不治本)。
坑三:Stub 区域漏配。一台设备配了 Stub,另一台没配,Hello 里的 Stub 标志不一致,邻居起不来。排查时看 Hello 报文里的 Options 字段。
坑四:参考带宽不一致。两台路由器参考带宽不同,开销计算标准不同,选路结果不一致,可能出现次优路径。全网统一参考带宽是基本要求。
8. 写在最后:几个能让你少走弯路的习惯
配 OSPF 这些年,我最大的体会是:规划比配置重要,验证比配置重要,文档比配置重要。配置命令就那么几条,但区域怎么划、Router ID 怎么分配、开销怎么设计,这些规划工作决定了网络后期的稳定性和可维护性。
几个具体习惯分享给你。第一,Router ID 永远手动指定,用环回口地址,规划好编号规则,比如核心用 1.x.x.x,分支用 2.x.x.x,一眼就能看出设备角色。第二,改任何参数前先想清楚影响范围,尤其是参考带宽、Hello 时间、区域类型这种全局性参数,改之前确认全网一致。第三,每次变更后立即验证,查邻居、查 LSDB、查路由表,三步走完再收工。第四,保留一份网络拓扑和区域规划文档,半年后你或者同事再来看,能省下大量回忆时间。
OSPF 基础就聊到这。它不难,但细节多,真正吃透需要在实际网络里反复验证。我建议你找个模拟环境,把多区域、Stub、NSSA、外部引入这些场景都搭一遍,亲手排几个故障,比看十篇文章都管用。