练HCIP的阶段,我估计很多人都在MGRE+OSPF这个组合实验上栽过跟头。单独看MGRE,就是多点GRE隧道,解决的是分支多、地址不固定时怎么建隧道的问题;单独看OSPF,也就是个链路状态路由协议,大家都会配。可一旦把OSPF搬进MGRE隧道,事情就变得很微妙:隧道接口上的网络类型、DR选举、hello超时,乃至路由递归,每一个环节都可能让你的邻居起不来、路由学不全。这篇文章把我自己当时做这个实验的全过程拆开讲,从拓扑设计、隧道配置、OSPF网络类型调整,到那个差点让我砸键盘的递归路由问题,一步步梳理清楚。适合正在备考HCIP的兄弟,也适合要在现网里搭多分支互联时临时抱佛脚的人。
1. 这个实验到底在练什么:一个典型的多分支互联场景
1.1 为什么MGRE和OSPF会纠缠在一起
MGRE全称是Multipoint GRE,多点GRE隧道。GRE本身是个隧道封装协议,能把私网报文包在公网里跑;MGRE则是对GRE的一种进化,它允许一个隧道接口对应多个对端,而不是像普通GRE那样一个接口只能连一个对端。
很多人在考HCIP之前其实已经会配普通GRE了。普通GRE的问题是啥?两个分支之间要通信,就得建一条独立的点到点GRE隧道。三个节点两两互联要三条隧道,六个节点就要十五条。分支数量一多,配置量爆炸,而且每条隧道都要单独维护。MGRE的思路是:所有分支都只有一个隧道接口,对端地址通过NHRP动态解析,真正做到了“一个接口,全互联”。
至于OSPF,它为什么非要和MGRE放一起练?因为隧道建好只解决了“能不能封装”,还没有解决“往哪边走”。隧道本质上是一条虚拟链路,要让各个分支的私网网段互相可见,就必须跑一个动态路由协议。OSPF作为IGP里最常用的协议,自然成了考试和实际项目的首选。MGRE加OSPF,相当于是把“动态隧道”和“动态路由”两个动态拼在一起,难点就来了。
1.2 模拟拓扑:总部加两个分支的网络到底怎么搭
我当时的实验拓扑很标准,模拟了一个“总部加两个分支”的场景,没有复杂到离谱,但足够把问题暴露出来。
核心是四台路由器:两台模拟公网,两台分支,不过为了专注MGRE和OSPF,我建议公网直接用两台路由器连成一条线,不需要搞复杂的ISP拓扑。具体来说:
- 总部路由器A:连接公网,私网侧有一个网段模拟总部内网。
- 分支路由器B:连接公网,私网侧有一个网段模拟分支内网。
- 分支路由器C:连接公网,私网侧有一个网段模拟另一个分支内网。
- 总部和分支之间通过公网路由器互联,公网部分只跑静态路由。
地址规划我放在下面这张表里,做实验时照着填就行。
| 设备 | 公网接口地址 | 隧道接口地址 | 私网回环接口 |
|---|---|---|---|
| 总部A | 192.168.12.1/24 | 10.0.0.1/24 | 172.16.0.1/32 |
| 分支B | 192.168.12.2/24 | 10.0.0.2/24 | 172.16.1.1/32 |
| 分支C | 192.168.13.2/24 | 10.0.0.3/24 | 172.16.2.1/32 |
| 公网路由器 | 192.168.12.254/24、192.168.13.254/24 | 无 | 无 |
这里有个关键点:隧道接口的地址网段用10.0.0.0/24,独立于所有私网网段。这个设计在后面递归路由那个坑里意义很大,先记住。
1.3 方案取舍:MGRE相比多条点到点GRE隧道的优势
我不太建议第一次做这个实验就急着敲命令,先把方案取舍想清楚比什么都重要。为什么中心分支用MGRE而不是直接在总部和每个分支之间各配一条GRE隧道?
核心原因是分支之间也需要互访。如果走普通GRE,总部和分支A一条隧道、总部和分支B一条隧道,但分支A要和分支B通信,就只能绕到总部再转,要么再手动加A到B的隧道。一旦分支数量增长到几十个,这条方案基本没法维护。
MGRE的思路是让任意两个节点之间都可以动态建立隧道。总部作为NHRP Server,所有分支向总部注册自己的公网地址;分支要访问另一个分支时,先向总部查询对端公网地址,然后直接建立一条分支到分支的隧道。这个“动态解析、按需建链”的过程,正是NHRP存在的意义。
另外从考试角度说,HCIP的实验考题非常喜欢考MGRE和OSPF的联动,因为这里面的网络类型、DR选举、路由递归全是易错点,一道题能串起好几个考点。把这个实验吃透,比单独背十道题有用。
2. 先把隧道底子打好:MGRE的配置顺序与NHRP机制
2.1 基础接口配置与路由可达性准备
我见过很多人一上来就配隧道,结果隧道接口状态永远是down,根源不是隧道配置错了,而是底层公网路由没通。MGRE隧道和其他隧道一样,必须满足一个前置条件:隧道的源地址和目的地址在公网里要能互相路由。
所以第一步老老实实把所有物理接口配好,包括公网接口地址、私网侧接口或回环接口。为了模拟真实网络,我给每台设备都配了回环接口,比如总部的172.16.0.1/32就是模拟总部内网。
公网部分我用最简单的静态路由打通。总部A到分支B的方向配置一条指向公网路由器的默认路由,分支B也配置默认路由,最终保证任意两个隧道的公网源地址之间可以互相ping通。
这里有一个经验:在模拟器里测试隧道建立之前,先ping通对端的物理公网地址,再开始配隧道。如果物理地址都不通,后面所有问题都会叠加在一起,排查起来非常痛苦。
2.2 MGRE隧道接口的完整配置模板
基础打通之后,进入主题。总部A的隧道配置,我给出一个经过验证的模板。
总部A的隧道接口:
interface Tunnel0/0/1 ip address 10.0.0.1 255.255.255.0 tunnel-protocol gre multipoint source GigabitEthernet0/0/1 nhrp network-id 100 ip nhrp map multicast dynamic分支B的隧道接口:
interface Tunnel0/0/1 ip address 10.0.0.2 255.255.255.0 tunnel-protocol gre multipoint source GigabitEthernet0/0/1 nhrp network-id 100 ip nhrp nhs 10.0.0.1分支C的配置和B基本一样,只是隧道地址换成10.0.0.3。逐条解释一下关键命令。
tunnel-protocol gre multipoint:指定隧道模式为多点GRE,这是MGRE和普通GRE最根本的区别。没有这条命令,Tunnel接口就是点到点GRE,配置思路完全不同。source GigabitEthernet0/0/1:指定隧道封装的源接口或源地址。注意这个接口必须是公网可达的接口。nhrp network-id 100:NHRP域标识。同一个MGRE网络里的所有设备,network-id必须一致。这个id就像是NHRP网络的身份证,不同域之间不会互相注册。ip nhrp map multicast dynamic:总部专用,表示接受分支发来的组播注册信息,并动态建立组播映射表项。没有这条,分支发来的NHRP注册请求无法被正确处理。ip nhrp nhs 10.0.0.1:分支专用,指定NHRP服务器地址。分支通过这个地址向总部的隧道接口发送注册请求。
这套配置里最大的坑是source接口的选择。我一开始用的是回环接口做source,想省事,结果分支的NHRP注册报文到了公网后,回包指向了回环地址,路由各种绕,最后隧道很多报文到达不了对端的隧道接口,OSPF邻居反复震荡。后来规规矩矩用物理公网接口做source,所有问题迎刃而解。如果非要用回环做source,必须确保回环地址在整个公网里是唯一可路由的,并且所有对端都知道去往这个地址的路由,否则别碰。
2.3 NHRP在中间扮演的角色:注册、解析与multicast映射
MGRE之所以能动态建隧道,完全靠NHRP在背后撑场子。我用一个前台接待处的类比来解释NHRP的工作过程。
总部A的NHRP Server就是前台。所有分支到达公网后,第一件事是向前台报到:“我是B,我的公网地址是192.168.12.2,我的隧道地址是10.0.0.2。”这个报到过程,在协议里叫NHRP Registration,对应命令ip nhrp nhs加注册请求报文。
如果分支B要访问分支C,B手头没有C的公网地址,于是B向NHRP Server发一个Resolution请求:“请告诉我10.0.0.3对应的公网地址是什么。”总部A查一下自己的NHRP表,把192.168.13.2返回给B。B拿到地址后,直接向C发起GRE隧道封装,后续B和C的通信就不再经过总部。这就是NHRP的解析过程。
还有一个组播映射的概念需要单独说。OSPF在广播网络类型下会发组播hello报文,但GRE隧道本身并没有组播能力。NHRP里的multicast映射,相当于把逻辑上的组播映射到真实的单播地址列表上。总部的ip nhrp map multicast dynamic就是动态维护这个列表,把每个注册上来的分支都加入组播分发名单。分支之间如果需要直接互访,可能也要配置静态的multicast映射指向总部,确保OSPF组播报文能送到正确的对端。
2.4 隧道是否真正建立的验证方法
隧道配完,不要急着配OSPF,先验证隧道本身。
在总部A上执行:
display nhrp brief正常情况下能看到分支B和C的注册信息,包括协议地址、隧道物理地址和接口状态。如果这条命令输出为空,先检查两件事:一是network-id是不是一致,二是分支到总部的公网路由是不是通。
再执行:
display tunnel-info all能看到Tunnel0/0/1的状态,如果显示Up,说明隧道协议层已经起来。物理接口和协议接口都Up,才能继续配OSPF。这个阶段我建议再测试一下分支B是否能ping通分支C的隧道地址,如果通,说明NHRP解析和动态隧道建立已经生效;如果不通,先别往下走,因为OSPF会掩盖很多底层问题,到时候你分不清是隧道问题还是路由问题。
3. OSPF在多点隧道上的脾气:网络类型与DR选举
3.1 隧道接口上的OSPF默认行为与第一次邻居建立失败
隧道配置没问题以后,我开始配OSPF,以为一切都会顺理成章。结果OSPF邻居一个也起不来,在路由器B上看邻居状态一直卡在Init或者ExStart。
根本原因在于OSPF对接口网络类型的判断机制。OSPF在不同物理链路上的默认网络类型不一样:以太网口默认是broadcast,串口默认是point-to-point。而隧道接口的本质是虚拟接口,它在OSPF里的默认网络类型既不是broadcast也不是简单的point-to-point,很多时候会被当成point-to-multipoint(p2mp)来对待。
p2mp没有问题,但问题出在OSPF p2mp网络类型在GRE隧道环境里,对组播hello的支持不完整。OSPF的邻居发现依赖hello报文,默认情况下hello是发往组播地址224.0.0.5的。MGRE隧道本身没有组播能力,如果没有NHRP的multicast映射把组播转成单播列表,hello就送不出去,邻居自然起不来。这个问题在模拟器里尤其明显,因为你很难第一时间想到是“组播被丢弃了”。
3.2 三种可用网络类型怎么选
既然默认行为不友好,就需要手动指定网络类型。在MGRE隧道接口上,OSPF一般有三种选择:broadcast、p2mp、nbma。
| 网络类型 | hello间隔 | 是否选举DR/BDR | 适用场景 | 缺点 |
|---|---|---|---|---|
| broadcast | 10秒/40秒 | 选举 | 全互联且希望减少邻接关系 | DR选举不稳定,非全互联时报文处理复杂 |
| p2mp | 30秒/120秒 | 不选举 | 星型、非全互联 | hello靠单播,需要额外指邻居 |
| nbma | 30秒/120秒 | 选举 | 帧中继等经典NBMA链路 | 配置复杂,现代网络极少用 |
我推荐大多数练习场景直接用broadcast,原因有两个。第一,配置最简单,只要指定网络类型并把DR优先级调好就行;第二,HCIP考试和常见厂商模拟器对broadcast的支持最成熟,排错资源多。p2mp其实也很实用,但在模拟器里需要配合静态或动态单播邻居配置,步骤繁琐,容易劝退新手。
3.3 手动指定网络类型与DR偏好配置
既然选broadcast,就要处理DR选举。OSPF在广播网段里会选举DR/BDR,所有的邻接关系建立都以DR为中心。在MGRE隧道里,DR最好由总部设备担任。如果分支设备成了DR,会出现一个问题:分支之间的hello组播可能无法正确转发,导致整个OSPF域的路由学习不稳定。
让总部当DR的办法是修改OSPF接口优先级。在总部A的Tunnel接口下配置:
interface Tunnel0/0/1 ip ospf network-type broadcast ip ospf priority 200在分支B和C的Tunnel接口下配置:
interface Tunnel0/0/1 ip ospf network-type broadcast ip ospf priority 0优先级为0表示设备不参与DR/BDR选举,这个设计很巧妙:分支们全都放弃竞选,总部自然成为唯一的DR。没有任何分支会和总部抢DR的位置,拓扑就稳定了。
OSPF进程配置也一起贴上。总部A:
ospf 1 router-id 1.1.1.1 area 0.0.0.0 network 10.0.0.0 0.0.0.255 network 172.16.0.0 0.0.0.255分支B:
ospf 1 router-id 2.2.2.2 area 0.0.0.0 network 10.0.0.0 0.0.0.255 network 172.16.1.0 0.0.0.255注意这里我把所有隧道接口都放进了区域0。MGRE环境坚持单区域是最省心的,多区域在这个虚拟链路组合里会引入不少区域间路由的麻烦,等基础实验跑通了再尝试也不迟。
3.4 邻居建立成功后的路由表现
配置改完,等一个hello周期,再看邻居状态:
display ospf peer brief正常情况下,总部A能看到两个邻居,状态是Full,分支B和C也各自能看到总部A的邻居状态为Full。这时候OSPF邻接关系就算建立成功了。
再查看路由表:
display ip routing-table ospf会发现总部、分支B、分支C的私网网段都出现在OSPF路由表里。比如在分支B上能看到172.16.2.0/24通过OSPF学习到,下一跳是10.0.0.3。这说明OSPF已经能在MGRE隧道上正常工作了。
不过先别高兴太早,我在这个阶段遇到了一个更隐蔽的问题,也是这篇博文最想讲的东西——递归路由。分支B虽然学到了分支C的网段,但有时候学完一分钟不到,路由就消失了,邻居也开始反复震荡。
4. 递归路由这个坑,我劝你一开始就避开
4.1 故障现象:邻居反复flapping,隧道一会通一会不通
我做完OSPF配置后,遇到了这个经典故障。一开始一切正常,路由表也好看,但过不了多久,分支B去往分支C的流量开始丢包,ping隧道地址也是时通时断。查看OSPF邻居,发现状态在“Full”和“Down”之间来回跳。
这种故障和典型的配置错误不一样,它不是你漏敲了一条命令,而是路由协议自身产生了一个逻辑矛盾。排查这类问题,不能只看邻居状态,要看数据转发路径。我当时盯着邻居状态看了很久,后来才意识到问题出在“去往隧道目的地址的路由”被OSPF自己污染了。
4.2 根因拆解:OSPF把自己的脚踩进公网路由
递归路由的核心逻辑是这样的:MCRE隧道的封装需要一个前提,即路由器必须知道“如何到达隧道对端的公网地址”。比如分支B要和分支C建立隧道,B的隧道目的地址是C的公网地址192.168.13.2,B在封装GRE报文时,要做一次路由查询:这个目的地址该往哪个接口扔?
正常情况,这个路由应该走公网静态路由或直连路由。但如果公网网段被宣告进了OSPF,或者OSPF从隧道学到了一个包含公网地址的汇总路由,那么路由查询的结果会变成:去往192.168.13.2的报文,应该从隧道接口Tunnel0/0/1出去。
问题就出在这里。从隧道接口出去意味着还要再做一次GRE封装,GRE封装后目的地址还是192.168.13.2,于是设备又查一次路由表,得到的结果又是从隧道接口出去。报文进入了一个无限循环,直到TTL耗尽被丢弃。这就是递归路由,英文叫Recursive Routing。
我当时的错误很典型:为了省事,我直接在全网执行了OSPF宣告公网网段的配置network 192.168.12.0 0.0.0.255,还把几个公网网段都宣告进去了。这样一来,公网网段在OSPF域里被当作普通内网网段广播到了所有隧道接口,隧道依赖的公网路由就被OSPF自己覆盖了。
4.3 完整排查链路:从邻居状态到路由表的逆向追踪
这个故障的排查过程本身很值得记录,比直接告诉你答案有价值。
第一步,在分支B上ping分支C的隧道地址,发现不通。
第二步,查看OSPF邻居状态,发现分支B和总部A之间的邻居在来回震荡。
第三步,查看NHRP表,发现B到C的注册和解析记录还在,说明隧道控制层面没有完全断。
第四步,查看display ip routing-table 192.168.13.2,这时候真相大白:路由表里最长匹配那条路由的出接口竟然是Tunnel0/0/1,而不是公网接口GigabitEthernet0/0/1。OSPF通过隧道学到了一个指向192.168.13.0/24的路由,而这条路由恰恰是报文去往C的公网地址时最匹配的。
第五步,顺着OSPF路由再查display ospf lsdb,确认这些公网网段确实在OSPF链路状态数据库里。至此根因确认:公网网段被宣告进了OSPF,形成了递归路由。
这个排查链路如果倒过来做,很多人会陷入“邻居为什么起不来”的死胡同里,反复调hello时间和DR优先级,完全跑偏。记住一个原则:邻居状态异常,先查路由,再看协议。
4.4 修复方案与预防习惯
修复方式很简单,从OSPF进程里撤销公网网段的宣告即可。
在总部A和两个分支上执行:
ospf 1 area 0.0.0.0 undo network 192.168.12.0 0.0.0.255 undo network 192.168.13.0 0.0.0.255撤销后,再次查看display ip routing-table 192.168.13.2,去往公网地址的路由会优选静态路由或直连路由,出接口重新指向物理公网接口。递归消失,OSPF邻居稳定在Full,分支之间的通信恢复正常。
比起修复,更重要的是预防习惯。我在之后的实验里给自己定了几条规矩:
第一,OSPF宣告范围只包含私网网段和隧道网段,公网网段一律不碰。隧道本质是虚拟链路,它依赖的下层物理路由必须保持独立,不能和OSPF学习到的路由混在一起。
第二,如果公司网络里确实存在跨内网访问公网地址的需求,用路由优先级做保护。在静态路由或直连路由上不做特殊动作,但通过调整OSPF外部路由的管理距离或优先级,确保内网学到的路由不会覆盖更优的物理路由。
第三,每次改完OSPF宣告,顺手display ip routing-table看一眼隧道目的地址的路由出接口,确认还是物理接口。这比等故障出现了再查要省心得多。
5. 练完这个实验之后,我总结的几条经验
5.1 模拟器环境里最容易忽略的三个细节
模拟器和真机有很多差异,这些差异在你敲命令的时候不会立刻暴露,但会在OSPF邻居建立阶段出来捣乱。
第一个细节是接口编号。不同模拟器或不同设备型号,公网接口的编号可能完全不同。有些设备上WAN接口不叫GigabitEthernet0/0/1,而是叫Serial或者XGigabitEthernet。配置source GigabitEthernet0/0/1之前,一定要用display ip interface brief确认一下实际接口名,否则隧道根本起不来。
第二个细节是NHRP的multicast映射。在总部设备上配置ip nhrp map multicast dynamic后,如果分支之间的OSPF hello依然发不出去,可以考虑在分支上也手动指定一条静态的组播映射到总部的隧道地址:
ip nhrp map multicast 10.0.0.1这条命令的作用是把分支要发出的组播报文,全部单播封装给总部的隧道地址,由总部再转给其他分支。
第三个细节是模拟器里的时钟和计时器。OSPF邻居状态机的变化严重依赖hello和dead计时器。如果设备时间不同步到秒级,某些模拟器会出现邻居反复进入ExStart的问题。虽然理论上OSPF不依赖绝对时间,但我在多个模拟环境里遇到过这类诡异现象,统一时间或者重启OSPF进程往往能解决。
5.2 一条命令一个动作:练实验的正确节奏
刚开始做实验的人容易犯一个毛病:照着网上的脚本一次性把全部配置粘贴进去,然后祈祷一次成功。这种习惯在HCIP阶段会吃大亏,因为一旦出了问题,你完全不知道是哪条命令引起的。
我的建议是每敲一批命令,就做一次验证,形成“配置—验证—配置”的节奏。配完物理接口,先ping公网;配完隧道,先display nhrp brief;配完OSPF,先看邻居状态再看路由表。每一步有问题,都能精确定位到具体协议的配置层面。
另外不要偷懒用全网通的配置生成工具。考试和实际排障时,最值钱的能力是“从现象倒推原因”。比如看到OSPF邻居卡在ExStart,你要能想到可能是hello参数不一致,或者是MTU问题,而不是傻傻地把所有配置删掉重来。
5.3 从考试到现网:这套技术组合到底用在哪
很多人练完MGRE加OSPF之后会问,这玩意现网里真的有人用吗?答案是肯定的,但场景比考试稍微复杂一点。
最常见的场景就是多分支机构互联,比如一个总部、几十个支公司,公网地址参差不齐,有的支公司是动态拨号上网,没有固定公网IP。这种场合下,普通GRE隧道的配置量会让你崩溃,而MGRE的NHRP注册机制天然支持动态公网地址的分支,只要它能主动访问总部的固定地址,就能完成注册和通信。
OSPF在这个场景里承担的是私网路由的分发职责。各分支的内网网段通过OSPF在隧道上互相通告,总部能看到所有分支的网段,分支之间也可以按需建链。加上路由汇总、过滤、认证这些高级特性,完全能撑起一套企业级的多分支互联网络。
我在实际项目里还总结出一个选型心得:如果分支数量少于五个,其实用静态路由加普通GRE也能凑合;但一旦超过十个分支,或者分支公网地址不固定,MGRE加OSPF就是最合理的选择。这个判断标准,比单纯背命令重要得多。
再分享一个小技巧。做这个实验的时候,我会刻意把OSPF的router-id全部手工固定,总部分配1.1.1.1,分支依次分配2.2.2.2和3.3.3.3。这样可以避免设备随机选择router-id带来的邻居建立延迟,也让后续排错时能一眼看出来拓扑关系。练完MGRE加OSPF之后,再回头去看HCIP里的路由章节,很多以前觉得抽象的概念,比如NBMA、DR选举、递归路由,都会变得非常具体,这是光刷题完全体会不到的效果。