☰
基于MGRE的OSPF动态路由配置:Hub-Spoke组网实践
2026/10/10 2:57:11 网站建设 项目流程

1. 为什么要把OSPF跑在MGRE上:场景、收益与坑

HCIP-Datacom阶段的进阶实验不少,但“基于MGRE的OSPF动态路由配置”这套组合拳,值得单独拿出来复盘。MGRE解决的是多点隧道自动建立的问题,OSPF解决的是隧道之上动态路由同步的问题,两件事单独看不难,一旦叠在一起,就会出现DR选举、组播映射、下一跳处理这些在普通以太网上很少碰到的细节。我最初做这个实验时,也是照着网上零散的配置片段敲,结果邻居状态一会儿卡在ExStart,一会儿路由表里出现“看起来能通但实际封装不了”的下一跳,折腾了整整一个晚上才把底层逻辑理顺。这篇文章就是我重新整理后的完整操作记录,适合正在备考HCIP的人,也适合在实际分支互联项目中需要设计MGRE承载OSPF的工程师。

先说明这个实验解决的真实问题。一家公司总部和多个分支组网,最简单粗暴的方案是每两个节点之间建一条点对点GRE隧道,形成全互联。但分支数量一旦增加到十个以上,隧道数量会按排列组合增长,配置和维护成本直接爆炸。MGRE的价值在于,所有分支只需要和中心节点建立隧道,分支之间的流量默认通过中心转发,新分支上线时只需要在本地配置一条指向中心的NHRP注册条目,中心甚至不用预先知道分支的公网地址。这使得“分支动态接入”成为可能。而OSPF在这些隧道上的作用,是把各节点的内部网段动态通告出去,避免每条路由都靠手工静态配置。

不过OSPF放在MGRE上,有两个天然摩擦点。第一,MGRE本质是NBMA(非广播多点接入)环境,OSPF在设计之初默认网络类型是广播型或点对点型,对NBMA的支持需要专门配置网络类型。第二,OSPF的Hello报文默认走组播地址224.0.0.5,而MGRE隧道底层并不天然支持组播,必须借助NHRP建立“组播映射”才能让组播报文被正确封装。很多人在这一步没搞明白,直接把Tunnel接口宣告进OSPF,结果邻居始终建立不起来。后面我会逐步拆开讲。

实验环境我建议用模拟器完成,拓扑不复杂,三台AR路由器就够了。R1作为中心节点(Hub),模拟总部出口;R2、R3作为分支节点(Spoke),模拟两个远端分支。三台设备的物理接口接入同一个广播域,模拟一个简单的承载网络,保证底层IP互通。这样能最大限度聚焦MGRE和OSPF本身,不被复杂的底层链路干扰。

2. 动手之前:地址规划、隧道模式与NHRP的关系

2.1 地址规划表:先定角色,再定地址

很多实验翻车不是配置敲错,而是IP地址规划混乱。MGRE隧道上要跑OSPF,需要预留一个独立的隧道子网,同时每个节点还需要一个稳定的环回地址用来当Router ID和测试连通性。我的规划如下:

设备角色物理接口地址环回地址Tunnel接口地址
R1Hub中心100.1.1.1/241.1.1.1/3210.1.1.1/24
R2Spoke分支100.1.1.2/242.2.2.2/3210.1.1.2/24
R3Spoke分支100.1.1.3/243.3.3.3/3210.1.1.3/24

物理网段有两点需要注意。第一,承载网地址不要宣告进OSPF区域,否则隧道和物理路径同时参与路由计算,很容易出现次优路径,甚至让故障排查变得混乱。第二,Tunnel地址必须和底层物理地址完全区分开,二者属于不同的逻辑层面,混用的话NHRP注册和OSPF邻居关系都会变得非常难理解。

环回地址在这里不只是用来测试。OSPF必须有一个稳定的Router ID,手工指定为环回地址是最稳妥的做法。同时,分支内部的业务网段我会用环回地址来模拟,比如R2的环回就是“分支2的业务网段”,这样验证路由时可以直接ping到2.2.2.2,非常直观。

2.2 隧道模式别混淆:点到点GRE和GRE P2MP

华为路由器上Tunnel接口的默认隧道协议是GRE,但默认模式更接近点到点。要做MGRE,必须在Tunnel接口下显式执行tunnel-protocol gre p2mp。这句话的意思是:把这台设备的隧道接口配置为“多点GRE”,即允许一个隧道接口下动态建立多个对端。没有这条命令,后续的NHRP配置基本不生效,或者会出现一些非常诡异的现象。

理解这一点,你需要把GRE和MGRE分开看。普通GRE隧道是“一根管子连两端”,配置时必须指定对端隧道地址和源接口,数据流向是确定的。MGRE则是“一个会合点加多个动态成员”,隧道接口只是定义一个逻辑入口,真正的对端关系由NHRP动态学习。中心节点不需要提前知道有多少分支,分支通过注册消息把自身的公网地址告诉中心,中心再把映射关系记录到NHRP表中。

所以配置顺序必须是:先切换Tunnel协议模式,再设置本端源地址,最后配置NHRP参数。如果顺序反了,有些版本会提示命令冲突,或者即使配置成功也不会按预期工作。

2.3 NHRP为什么是MGRE的控制面

NHRP(下一跳解析协议)在MGRE里的角色,可以理解成“动态通讯录”。分支节点启动后,向中心节点发送注册请求,中心在自己的NHRP表里记录下“隧道地址10.1.1.2对应公网地址100.1.1.2”这条映射。后续分支要向某个隧道地址发包时,先查NHRP表,决定以太网报文封装到哪个真实的IP地址。

OSPF跑在MGRE上,还需要解决组播问题。OSPF的Hello报文是组播的,但GRE隧道不是天然组播链路,不可能像交换机那样把组播报文“广播”给所有分支。解决办法是在中心节点配置nhrp entry multicast dynamic,这句的意思是:所有动态注册上来的分支,自动加入中心节点的组播发送列表。这样中心把组播Hello发给R2、R3时,会分别封装成两个单播包送出去。分支节点默认不会向其他分支发送组播,所以整个OSPF邻居关系只会发生在中心和每个分支之间,分支之间不直接建立OSPF邻居,这其实是我们要的结果。

3. 配置实录:Hub与Spoke的完整命令

3.1 中心节点R1的完整配置

先登录R1,设置设备名并配置物理接口和环回口:

system-view sysname R1 interface GigabitEthernet0/0/0 ip address 100.1.1.1 255.255.255.0 undo shutdown interface LoopBack0 ip address 1.1.1.1 255.255.255.255

然后创建Tunnel接口。这是我的核心配置,每一条都有目的:

interface Tunnel0/0/0 ip address 10.1.1.1 255.255.255.0 tunnel-protocol gre p2mp source 100.1.1.1 nhrp network-id 100 nhrp entry multicast dynamic

source 100.1.1.1指定了隧道报文的源地址,也就是本端物理接口地址。nhrp network-id 100定义了一个NHRP域,同一个MGRE网络内的所有节点必须配相同的network-id,否则互相不认。这里我选100,实际生产环境用网段序号或区域编号都行,关键是要全网络一致。

最后配置OSPF。我只宣告环回和Tunnel网段,物理接口100.1.1.1不宣告:

ospf 1 router-id 1.1.1.1 area 0.0.0.0 network 1.1.1.1 0.0.0.0 network 10.1.1.0 0.0.0.255

为什么要用区域0?因为MGRE网络本身可以看成一条逻辑上的骨干链路,所有节点都应该在同一个OSPF区域,最自然的选择就是区域0。如果分支很多且各自有大量内部明细路由,后续可以再拆区域,但在基础实验里保持区域0最简单,也最容易排查问题。

3.2 分支节点R2、R3的配置差异

分支节点和中心节点最大的不同在于:分支需要主动向中心注册,并且要指定中心的NHRP条目。R2的配置如下:

system-view sysname R2 interface GigabitEthernet0/0/0 ip address 100.1.1.2 255.255.255.0 undo shutdown interface LoopBack0 ip address 2.2.2.2 255.255.255.255 interface Tunnel0/0/0 ip address 10.1.1.2 255.255.255.0 tunnel-protocol gre p2mp source 100.1.1.2 nhrp network-id 100 nhrp entry 10.1.1.1 100.1.1.1 register

关键在最后一行:nhrp entry 10.1.1.1 100.1.1.1 register。前半部分是中心的隧道地址和公网地址,后半部分的register表示本端要向这个地址发送NHRP注册消息。如果没有register关键字,这条条目只是静态映射,NHRP不会主动注册,中心节点的组播列表里也不会出现这个分支,OSPF邻居很可能起不来。

R3的配置完全类似,把物理接口、环回和Tunnel地址换成对应网段即可。这里我强调一下,分支节点之间不需要配置对方的NHRP条目。默认情况下,分支之间的数据要经过中心转发,因此分支只需要认识中心就够了。

3.3 配置完成后如何快速验证

配置完不要急着看OSPF,先验证NHRP注册是否成功。在R1上执行:

display nhrp peer all

正常情况下可以看到两条对端记录,状态为up。R2和R3的NHRP表里,应该能看到一条指向中心的记录。如果NHRP表是空的,后面OSPF一定起不来,这时候首先检查network-id、source地址以及承载网连通性。

然后验证OSPF邻居:

display ospf peer brief

我在R1上看到的输出大致是这样的:

OSPF Process 1 with Router ID 1.1.1.1 Peer Statistic Information Area Id Interface Neighbor Id State 0.0.0.0 Tunnel0/0/0 2.2.2.2 Full/ - 0.0.0.0 Tunnel0/0/0 3.3.3.3 Full/ -

两个邻居都达到Full状态,说明OSPF正常建立了邻接关系。再查看路由表,R2上应该能看到2.2.2.2自己的路由,同时也能看到3.3.3.3的路由,下一跳是10.1.1.1,也就是中心节点的Tunnel地址。这个下一跳非常重要,后面我会专门讲它为什么不是分支地址而是中心地址。

最后做一次跨分支连通性测试。在R2上ping 3.3.3.3,能通就算成功。我建议同时加上-a 2.2.2.2指定源地址,确保测试走的是环回而不是物理接口。

3.4 顺手做的收敛调优

实验能跑通之后,我习惯调整一下OSPF Timer,让收敛速度更快。Tunnel接口在P2MP网络类型下,OSPF默认Hello间隔是30秒,Dead间隔是120秒。如果分支数量多,这个默认值偏保守,故障感知会非常慢。我会统一改成10秒和40秒:

interface Tunnel0/0/0 ospf timer hello 10 ospf timer dead 40

需要提醒的是,同一OSPF广播域内所有节点的Timer必须一致,否则邻居建立会失败。所以三个设备都要改,不能只改中心节点。

4. 把OSPF网络类型选对:P2MP、Broadcast还是NBMA

4.1 先确认Tunnel接口的OSPF网络类型

这是整个实验里最容易踩坑的一步。很多人在Tunnel接口下配置完OSPF后,不会去主动查接口网络类型,直接去看邻居,结果出了问题根本不知道从哪排查。在华为VRP上,Tunnel接口运行OSPF时,默认网络类型是P2MP。用下面这条命令可以确认:

display ospf interface Tunnel0/0/0

如果发现显示的网络类型不是P2MP,而是Broadcast或NBMA,不要慌,手动指定为P2MP即可:

interface Tunnel0/0/0 ospf network-type p2mp

为什么P2MP是MGRE下的最优选择?因为P2MP网络类型允许一个接口连接多个节点,但不需要像NBMA那样手工指定邻居列表,也不需要像Broadcast那样进行DR选举。它天然适合“一个中心带多个分支,分支之间不建立邻接关系”的拓扑。

4.2 别轻易改成Broadcast:DR选举会把路由搞乱

我在网上看到过不少配置教程,把Tunnel接口的OSPF网络类型改成Broadcast,理由是“模拟以太网环境,让所有节点自动建立邻居”。这个思路在物理拓扑完全互联的场景下可行,但在MGRE这种逻辑上非广播的链路里,非常危险。

原因是Broadcast网络类型会触发DR和BDR选举。在物理以太网中,所有路由器都在同一个二层域,DR的选择不会影响连通性,因为即使不是DR,也能通过交换机直接发送组播。但MGRE底层没有这种广播能力,组播报文必须依赖NHRP组播映射一条条封装。如果某个分支被选成DR,中心节点未必会向它发送组播Hello,导致OSPF邻居建立不上,或者即使建立了,路由表的完整度也完全不可控。

更进一步说,就算你强行把中心节点配置成DR,OSPF在Broadcast网络类型下只会让DR和BDR与其他路由器建立Full邻接关系,非DR之间只停留在2-Way状态。如果某两个分支之间的路由要靠二者直接交换,这条路径就断了。P2MP模式则不同,OSPF不会区分DR/BDR,中心与每个分支都形成Full邻接,路由完整度有保障。

4.3 P2MP模式下下一跳为什么会被“强制改写”

这是P2MP网络类型最容易被忽略的细节。在R2的路由表里,到达R3环回3.3.3.3的下一跳是10.1.1.1,而不是10.1.1.3。很多初学者会困惑:明明R3的Tunnel地址是10.1.1.3,为什么下一跳指向中心?

这是因为在P2MP网络中,OSPF默认把通过该接口通告出去的路由的下一跳设置为“到达目的节点的相邻接口地址”。对于R2来说,它和R3之间没有直连的OSPF邻居关系,R3的路由LSA是由中心R1中转的。R1为了让R2能把数据正确地封装到中心,会在LSA转发时把下一跳改写为自己的接口地址。这样R2发送到3.3.3.3的数据包,隧道目的地址是10.1.1.1,再由中心通过自己的NHRP表转发给R3。

理解了这一点,你就明白了为什么中心节点的nhrp entry multicast dynamic如此关键:它不仅是OSPF组播Hello的发送机制,也是数据面转发时把隧道地址“翻译”成真实公网地址的查询依据。如果没有中心这个翻译角色,R2就算知道下一跳是10.1.1.1,也不知道这个地址在物理网络上该封装到哪个目的IP。

4.4 通过Cost控制分支互访路径

在默认配置下,分支之间的流量全部经过中心转发。这个路径是否符合预期,取决于业务需求。如果分支之间有大量实时流量,不想绕行中心,可以考虑在全互联的MGRE环境下让分支间直接建立OSPF邻居,或者在中心启用NHRP的shortcut特性。但基础实验中,让流量经过中心反而是最简单稳定的设计。

不过有一点值得注意,Tunnel接口的OSPF Cost如果设置不当,可能让分支认为“直连隧道”比“走中心”更优,从而产生非预期的路径选择。实际环境中我建议明确给Tunnel接口配置一个统一的Cost值,比如:

interface Tunnel0/0/0 ospf cost 10

这样无论底层物理链路带宽有多少差异,OSPF在计算隧道内路由时都有一个确定的开销基准,不会因为承载网走的是千兆还是百兆产生歧义。

5. 真实排障实录:从“邻居卡在ExStart”说起

5.1 现象一:邻居卡在ExStart/Exchange

我最初配置完,在R1上执行display ospf peer brief,发现R2的邻居状态一直卡在ExStart,就是不进Full。当时我第一反应是隧道问题,查了NHRP表发现注册都正常,物理链路也通,于是陷入困惑。

后来才意识到是MTU问题。Tunnel接口默认MTU是1500字节,但GRE封装会额外增加至少24字节的报文头。OSPF的DD报文如果按1500字节发送,经过GRE封装后会超过物理接口的MTU,导致对端收不到完整报文,邻居协商就卡在ExStart阶段。

解决办法是统一降低Tunnel接口的MTU。我在三台设备上都执行了:

interface Tunnel0/0/0 mtu 1400

然后重启OSPF进程或清除接口状态,邻居马上就从ExStart推进到Full。这个坑在物理链路带宽不高时格外明显,建议做实验一开始就把MTU设置好,不要等出了问题再排查。

5.2 现象二:邻居Full了,路由却缺胳膊少腿

还有一次,我明明看到R1上有两个Full邻居,但R2的路由表里只有中心的路由,看不到R3的环回。当时我怀疑是OSPF区域配置不一致,检查了一圈都没问题。最后用display ospf interface Tunnel0/0/0一看,才发现接口网络类型被之前的配置脚本改成了Broadcast。

这种情况下,R2和R3之间没有建立OSPF邻接关系,R3的路由LSA能否传到R2,完全取决于DR选举结果和中心节点的转发能力。如果不巧R2或R3被选成了DR,而中心节点又不是DR,就很容易出现路由不完整。我当时的解决办法很简单:把那台设备上的Tunnel接口网络类型改回P2MP,清掉OSPF进程重新协商,所有路由就正常了。

这里要强调一个习惯:修改接口网络类型后,一定执行reset ospf process或者把接口先shutdown再undo shutdown,否则旧邻居关系不会立刻重建,状态可能一直停留在旧的网络类型判断上。

5.3 现象三:ping通了,但traceroute路径和预期不符

路由表看起来完全正常,跨分支ping也通了,但客户问我“分支互访的路径是不是直连”?我在R2上执行traceroute 3.3.3.3,发现第一跳就是R1的Tunnel地址,第二跳才是R3的Tunnel地址。这其实不是故障,而是MGRE默认的hub-spoke转发模型。

如果确实需要分支间流量不绕中心,需要额外启用NHRP的shortcut功能,让分支在转发时主动向中心查询目的地的真实公网地址,然后建立直连隧道。这个功能涉及更多配置参数,建议放到实际有需求的场景中再研究。基础实验阶段,看到traceroute路径经过中心,说明数据面工作正常,不需要怀疑配置有误。

我通常在交付文档里会主动写清这一点,避免后续运维人员把正确的路径当成环路去排查,浪费大量时间。

5.4 排查命令速查表

为了方便排障,我把常用命令整理成一张速查表:

排查目标关键命令关注点
底层IP连通ping 100.1.1.x物理链路是否正常
NHRP注册状态display nhrp peer all对端映射是否up,flag是否为register
隧道组播映射display nhrp entry multicast中心是否有分支的动态组播条目
OSPF接口状态display ospf interface Tunnel0/0/0网络类型、MTU、Timer是否匹配
OSPF邻居状态display ospf peer brief状态是否Full,Area是否一致
路由表完整性display ip routing-table protocol ospf各环回路由是否存在,下一跳是否合理
数据面转发路径traceroute 某个环回地址是否按预期经过hub转发

6. 几个能让配置更稳的小技巧

6.1 把Tunnel地址设在独立子网,别偷懒

我见过有人为了省地址,把Tunnel接口配置成ip address unnumbered interface LoopBack0,让隧道地址直接复用环回地址。这个配置在纯GRE点对点下能用,但在MGRE环境下会让NHRP表项的逻辑变得混乱,尤其是中心节点要做组播映射时,区分“环回地址”和“隧道协议地址”的边界会非常模糊。建议老老实实划一个独立子网给隧道,后续加分支也方便。地址规划省下来的那点资源,往往会在排障时加倍还回去。

6.2 BFD联动OSPF,让隧道故障暴露更快

OSPF在网络故障后,主要靠Dead Timer来感知邻居失效。如果按前面调优设置了Dead 40秒,在分支业务敏感的组网里仍然太慢。这种情况下可以启用BFD联动OSPF:

interface Tunnel0/0/0 ospf bfd enable

启用后,OSPF会为每个邻居建立BFD会话,当承载链路出现中断或严重丢包时,BFD能在毫秒级检测到,并把故障通告给OSPF,实现秒级甚至毫秒级收敛。需要注意,BFD报文本身也要经过NHRP映射,所以在中心节点要确保组播映射和NHRP表项是完整的,否则BFD会话可能起不来。

6.3 物理接口千万别顺手宣告进OSPF

这是我觉得最值得强调的生产经验。无论是实验还是实际项目,总有人因为“想省事”,直接把所有接口都宣告进OSPF,结果物理接口和Tunnel接口同时出现在路由表里。这个时候流量到底走隧道还是走物理链路,完全取决于OSPF Cost对比,一旦物理链路Cost更小,分支间的流量就会绕到奇怪的路径上,甚至出现来回路径不一致的问题。

正确的做法是,OSPF只宣告Loopback和Tunnel网段。物理承载网保持一个独立的IGP域,或者干脆用静态路由保证底层互通。这个原则不仅适用于MGRE,任何隧道叠加场景都应该遵守。

6.4 模拟器与真机的几个差异

我用模拟器做实验时遇到过几个和真机行为不完全一致的地方。比如模拟器里NHRP注册速度很快,几乎没有延迟;真机上如果中心节点负载高,注册可能出现稍许延迟,导致OSPF邻居建立慢。另外,模拟器对MTU问题表现得非常“宽容”,我甚至见过默认1500 MTU也能正常协商的情况,但真机上一般不行。所以实验做完后,如果有条件,建议在真机或仿真程度更高的环境里再跑一遍,重点验证MTU、BFD和NHRP注册超时这三个点。

最后说一点我自己的操作体会。MGRE加OSPF这套组合,本质上是一个“信令面”和“数据面”解耦的网络模型:NHRP负责动态发现,OSPF负责路由同步,GRE负责封装转发。把每一层负责的事情在脑子里拆清楚,配置和排障都会轻松很多。做实验时不要急着敲命令,先画一张拓扑图,标注好每个节点的角色、隧道地址和NHRP映射,再动手配置,这样的人为失误至少能减少八成。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询