ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

MGRE+NHRP综合实验:动态分支组网、OSPF路由与故障排查

MGRE+NHRP综合实验:动态分支组网、OSPF路由与故障排查

1. 先把图纸画清楚:MGRE 综合实验到底在解决什么问题

MGRE(Multipoint Generic Routing Encapsulation,多点通用路由封装)这个技术点,我是被一个很具体的需求逼着吃透的:总部有一条固定公网地址,下面挂了几个分支,分支用的是动态地址,随时可能变;业务上要求分支之间能直接互访,而不是所有流量都绕回总部再转发。最早我按老办法,在总部给每个分支配一个点对点 GRE 隧道接口,三个分支还行,到第五个分支的时候配置已经难看了,每加一个点,中心设备就要新建接口、加静态路由、改路由协议的网段声明,运维成本几乎是随分支数量线性增长的。后来换成 MGRE 加 NHRP 的组合,中心只留一个多点隧道接口,分支自己注册上来,这才是标题里“MGRE+综合实验”这套东西真正的价值所在。

先把这套实验的核心讲明白:MGRE 是 GRE 的一个变种,传统 GRE 隧道两端的隧道地址是“点对点”绑定的,一个接口对应一个对端;而 MGRE 的隧道接口被配置成“多点”模式,它本质上是一个虚拟的广播型或非广播型网段,多个对端可以共用同一个隧道接口、同一个隧道网段。但多点模式带来一个新问题——设备怎么知道某个隧道地址对应哪个公网地址?这就是 NHRP(Next Hop Resolution Protocol,下一跳解析协议)要干的事,它像是隧道网段里的“地址簿”,负责把隧道内的目标地址翻译成真实的公网出口地址。所以 MGRE 和 NHRP 在工程实践里几乎永远是绑在一起出现的,缺一个这套方案就跑不起来。

这套综合实验适合谁看?我的判断是:已经把静态路由、OSPF 基础、GRE 隧道单独玩过一遍的网络方向学习者,或者手上有分支组网需求、想验证方案可行性的运维人员。完全没有接触过隧道概念的新手也能跟着做,但需要先把“封装”这件事想明白——你可以把 GRE 理解成给原始数据包套了一个新的快递外箱,外层写的是公网收发地址,内层还是你自己的私有地址,中间的传输网络只认外层箱子,看不到里面的内容。MGRE 只是让这个“外箱”支持一对多的收件人而已。

我在这套实验里踩过的坑,绝大多数不在“能不能通”上,而在于“通得不稳”“某些方向通某些方向不通”“小包能过大包全丢”这类隐蔽问题。所以下面的内容我会把配置拆开讲,但重点放在每一步为什么这么配、配错了会以什么形式表现出来。这一点比配置本身重要得多,因为不同设备的命令行拼写有差异,你在自己环境里照抄大概率会遇到一两个字段对不上,理解了意图才能改对。

1.1 从一次分支互访的需求说起

假设现在有四台路由器:一台在中心机房,我们叫它 Hub;三台在分支,叫 Spoke1、Spoke2、Spoke3。Hub 有一条稳定的公网地址,三个分支各自通过不同的接入方式上网,出口地址不固定,其中 Spoke3 还藏在一台做地址转换的设备后面。每个站点后面挂一个业务网段,要求是:任意两个站点的业务网段能互相访问,Hub 上的业务网段是共享资源,所有分支都要能访问。

如果用最笨的办法——全网状的点对点 GRE,Spoke1 需要建两条隧道分别指向 Spoke2 和 Spoke3,Spoke2 也要建两条,最后是 6 条隧道,配置量是节点数的平方级。更要命的是分支地址是动态的,今天配好的对端地址明天可能就失效了,维护起来非常痛苦。换成 Hub-and-Spoke 的静态 GRE,每个分支只跟 Hub 建一条隧道,配置量降下来了,但分支之间的流量必须先到 Hub 再转发,如果分支之间有大流量(比如备份、文件同步),Hub 的出口带宽会被白白吃掉一大半,而且延迟翻倍。

MGRE 加 NHRP 的组合解决的就是这个矛盾:物理上还是 Hub-and-Spoke 的星型结构,控制面和初始流量走 Hub,但当 Spoke1 要访问 Spoke2 时,NHRP 会把这个请求“翻译”出来,Spoke1 发现目标的实际公网地址可以直接到达,就建立一条临时的直连路径,业务流量不再经过 Hub。这个机制在实验里的验证方式非常直观——先看流量怎么走,再看 NHRP 表项里有没有多出来的直连映射,一看就明白。

1.2 三种隧道方案的真实取舍

做方案选型的时候,我把三种常见做法放在一起对比过,结论是各有各的适用边界,没有绝对优劣。

方案中心配置量分支互访路径分支地址动态支持适用规模
全网状点对点 GRE高,节点数平方级直连差,地址变化需改配置3 个节点以内
星型静态 GRE低,每分支一个接口绕行中心差5 个分支以内且互访少
MGRE + NHRP低,中心一个接口可直连好,自动注册学习中等规模,10 到 50 个分支

这张表里最容易被忽略的是“分支地址动态支持”这一列。静态 GRE 的对端地址是写死在配置里的,分支换了宽带、运营商重新分配地址,隧道立刻断,必须有人上去改配置。MGRE 的分支是被动注册的,中心不需要预先知道分支地址,分支上来自己报,中心的 NHRP 表自动学习,这个差别在真实运维里价值极高——它把“变更”从人工操作变成了协议行为。

另一个取舍点是安全。裸 GRE 不加密,内层数据在传输网里是裸奔的。这套实验里我先跑通基础连通性,最后再把 IPSec 套在隧道外层做加密,这是典型的做法。要注意顺序:先让隧道和路由稳定运行,再加加密,否则一旦加完不通,你无法判断是隧道问题、路由问题还是加密协商问题,排查成本会翻好几倍。这是我自己吃过亏的教训,一次性把加密和隧道都配上去,然后花了两个小时在三个方向之间反复怀疑。

1.3 地址与角色规划表

实验开始前把地址规划好,能省掉大量返工。下面是我用的这一套,全部使用文档保留段,不会跟真实环境冲突。

角色隧道地址公网出口地址业务网段备注
Hub172.16.10.1/24203.0.113.1/24192.168.10.0/24隧道域中心,OSPF 的 DR
Spoke1172.16.10.11/24203.0.113.11/24192.168.11.0/24固定地址分支
Spoke2172.16.10.12/24203.0.113.12/24192.168.12.0/24固定地址分支
Spoke3172.16.10.13/24198.51.100.13/24192.168.13.0/24位于地址转换设备之后

隧道网段选 172.16.10.0/24 而不是常见的 /30,是因为多点隧道本身就是个网段,需要给未来新增的分支留出地址空间。这里有个细节:隧道网段和业务网段必须是完全独立的两个地址空间,不能重叠,也不能跟传输网重叠。我在早期实验里曾经把隧道网段配成了业务网段的一个子集,结果路由表里出现两条指向同一目的地的路由,一条走隧道一条走直连,流量走向完全失控,排查了大半天才发现是地址规划的问题。

传输网部分,Hub 和 Spoke1、Spoke2 都在 203.0.113.0/24 这个模拟的“公网”里,Spoke3 在 198.51.100.0/24,中间用一台路由器模拟运营商网络,两边各跑一条静态路由或者跑个简单协议保证互通。这一步别偷懒,一定要在起隧道之前先 ping 通——底层不通的情况下折腾隧道配置,纯属浪费时间。

2. 底层先通、隧道后起:MGRE 建立阶段的配置拆解

配置顺序在这个实验里是有严格逻辑的,不是随便排的。我的习惯是四步走:底层地址和路由、隧道接口与 NHRP、隧道内路由协议、分支互访验证。这四步之间是强依赖关系,前一步没验证通过就进下一步,后面出的问题会互相掩盖,你看到的故障现象和真实原因之间可能隔着两三层。

下面给出的配置我按通用命令风格书写,字段含义是标准的,各家设备在拼写和默认值上会有差异,比如有的设备把多点模式写成接口下的一个模式开关,有的把 NHRP 的注册命令拆成两条。你在自己环境里遇到对不上的地方,抓住“这个字段要表达什么”来判断,比死记命令有用。

2.1 Underlay 只做一件事:让两端的隧道源地址互相可达

隧道源地址是整个 MGRE 的地基。Hub 用哪个地址做隧道源,分支就必须能路由到这个地址;分支用哪个地址做隧道源,Hub 也必须能路由回来。这里我强烈建议用 LoopBack 接口作为隧道源,而不是物理接口。原因很实际:物理接口一旦因为链路抖动 down 掉,隧道接口会跟着 down,所有经过这条隧道的路由瞬间撤销,然后链路恢复、隧道重建、路由重新收敛,整个过程对业务来说就是一次闪断。用 LoopBack 的话,只要还有任意一条路径能到达这个 LoopBack 地址,隧道就不会断。

Hub 上的基础配置大致是这样:

interface LoopBack0 ip address 10.255.255.1 255.255.255.255 interface GigabitEthernet0/0 ip address 203.0.113.1 255.255.255.0 ip route 0.0.0.0 0.0.0.0 203.0.113.254 ip route 198.51.100.0 255.255.255.0 203.0.113.254

这里 203.0.113.254 是模拟运营商的那台设备的接口地址,最后一条静态路由是为了让 Hub 能到达 Spoke3 所在的网段。在真实环境里这一步通常由默认路由加动态路由完成,实验里为了可控就用静态。

分支侧类似,配好接口地址加一条默认路由指向运营商模拟设备。配完之后的第一件事不是急着起隧道,而是逐个 ping:Hub ping Spoke1 的出口地址、ping Spoke2 的出口地址、ping Spoke3 的出口地址,反过来也 ping 一遍。全部通,再往下走。这一步看起来啰嗦,但它能把“路由不通”和“隧道配错”这两类问题彻底隔离开,后面排查范围直接缩小一半。

提示:如果 Spoke3 位于地址转换设备之后,从 Hub 主动 ping 它的出口地址大概率是 ping 不通的,这是正常现象,不要误判为底层故障。判断标准改成“Spoke3 能 ping 通 Hub 的出口地址”即可,因为注册是分支主动发起的,单向可达就够。

2.2 中心节点的多点隧道接口逐行解释

Hub 上的隧道接口是整个实验的核心,我把它逐行拆开说。

interface Tunnel0 ip address 172.16.10.1 255.255.255.0 tunnel source LoopBack0 tunnel mode gre multipoint tunnel mtu 1400 ip nhrp network-id 100 ip nhrp authentication labkey ip nhrp map multicast dynamic ip tcp adjust-mss 1360 ip ospf network broadcast ip ospf priority 255

tunnel mode gre multipoint这一行是整个方案的分水岭。配置了它,这个接口就不再绑定单一对端,而是变成一个可以容纳多个对端的虚拟网段。没配这一行,接口就是点对点模式,NHRP 的相关命令大部分会失效或者行为异常。

tunnel mtu 1400是必须手动设的。物理接口 MTU 通常是 1500,GRE 封装会额外增加 24 字节(外层 IP 头 20 字节加 GRE 头 4 字节),如果不调整,隧道内的大包会被分片或者直接丢弃,表现出来的现象是“ping 小包通、大包不通”“网页打不开但能 ping 通”。1400 是留了余量的保守值,真实环境里如果外层还有额外封装(比如再套一层加密),要再往下减。

ip nhrp network-id 100是隧道域的标识,所有参与这个 MGRE 域的设备必须配成同一个值,不一致就直接注册失败,这是最常见的配置错误之一。它的作用类似一个“域号”,防止同一个物理网络里存在多个 MGRE 域时互相串台。

ip nhrp authentication labkey是简单的认证,防止随便一台设备往你的隧道域里注册。实验里用明文就够了,生产环境配合 IPSec 使用。

ip nhrp map multicast dynamic这一行只在 Hub 上配,作用是允许把隧道接口上的多播和广播流量复制给所有注册上来的分支。路由协议靠多播建立邻居,没有这行配置,分支的路由协议报文到不了 Hub,邻居永远起不来。这一行的缺失是我见过最高频的“隧道通了但路由不通”的原因。

ip tcp adjust-mss 1360是补充手段,它会在经过设备的 TCP 三次握手阶段修改 MSS 通告值,让对端主动把包切小。这个只对 TCP 生效,UDP 和 ICMP 不受影响,所以它不能替代tunnel mtu,两者要一起配。1360 的算法是 1400 减去 40 字节的 TCP/IP 头,留一点余量也行,一般不低于 1300。

ip ospf network broadcast和ip ospf priority 255这两行是为路由协议服务的,下面第三章会详细说原因,这里先记住:多点隧道默认的网络类型在某些设备上是非广播的,不显式改成广播型,OSPF 邻居关系建立会有问题。

2.3 分支节点注册:NHRP 客户端三件套

分支的配置看着比 Hub 复杂,其实逻辑很简单:告诉它“中心是谁”“我怎么找到中心”“我允许哪些多播过去”。

interface Tunnel0 ip address 172.16.10.11 255.255.255.0 tunnel source LoopBack0 tunnel mode gre multipoint tunnel mtu 1400 ip nhrp network-id 100 ip nhrp authentication labkey ip nhrp nhs 172.16.10.1 nbma 203.0.113.1 multicast ip nhrp map 172.16.10.1 203.0.113.1 ip nhrp map multicast 203.0.113.1 ip tcp adjust-mss 1360 ip ospf network broadcast ip ospf priority 0

ip nhrp nhs指定的是 NHS(Next Hop Server,下一跳服务器),也就是 Hub。这里填的是 Hub 的隧道地址 172.16.10.1,后面的nbma 203.0.113.1告诉设备这个隧道地址对应哪个真实地址,multicast关键字表示多播流量也发给它。这一条命令基本等价于下面两条ip nhrp map的合并写法,不同设备可能只支持其中一种,两种都配也不冲突。

ip nhrp map multicast 203.0.113.1单独列出来是因为有些场景下nhs命令不带多播参数,需要单独指定。分支侧不能像 Hub 那样用dynamic,因为分支只需要把多播发给中心一个目标,用静态映射更精确。

三个分支的配置除了隧道地址不同,其余完全一样。Spoke3 有一个特殊点:如果它位于地址转换设备之后,隧道源地址要写成转换后的地址或者用接口地址让设备自动处理,具体取决于转换设备的类型。这部分在实验里我先跳过了地址转换的复杂性,让 Spoke3 直接使用 198.51.100.13 出口,等基础跑通后再单独验证。

2.4 注册状态核验与 MTU、MSS 的一次性调优

配置敲完之后,先别急着配路由协议。第一步是在 Hub 上看 NHRP 表:

show ip nhrp

正常情况下应该能看到三条注册记录,每条记录包含隧道地址、对应的真实地址、注册时间和状态。如果一条都没有,说明分支根本没注册上来,排查顺序是:隧道接口 up 了没有、network-id 是否一致、认证密钥是否一致、底层能不能通。

第二步是在分支上看:

show ip nhrp nhs

这条命令看的是它认为的中心是谁、状态是不是 reachable。状态显示 incomplete 或者 failed,基本就是 Hub 地址或 nbma 地址配错了。

第三步是隧道内的连通性测试。从 Hub ping 172.16.10.11,从 Spoke1 ping 172.16.10.1。这个 ping 走的是隧道,能通说明封装解封装正常。这时候可以用大包 ping 验证 MTU:

ping 172.16.10.11 size 1400 df-bit

df-bit是禁止分片,如果这个包不通而小包通,说明链路上某一段的 MTU 比你以为的小。改法有两种,一是继续调小tunnel mtu,二是让链路上的设备支持分片。实验中建议直接把 MTU 调到 1400 然后测 1372 字节的包(1400 减去 28 字节的 ICMP/IP 头),全部通就说明配置对了。

注意:tunnel mtu设得太小会浪费带宽、增加分片开销,设得太大则大包丢失。经验值是在物理 MTU 基础上减去 24 字节以上,套了 IPSec 再减 50 到 70 字节。不要凭感觉,用带df-bit的 ping 从大到小二分找出真实可用值,这是最靠谱的办法。

3. 动态路由与分支直连:让隧道真正承载业务

隧道通了只是完成了第一步,接下来要让路由协议在这个多点隧道上跑起来,让每个分支的业务网段被其他站点学到。这一步的坑比隧道建立阶段多得多,因为路由协议的很多默认行为是为点对点链路设计的,套在多路访问的隧道网段上会出现各种意外。

3.1 网络类型为什么必须显式指定

OSPF 有五种网络类型,默认情况下隧道接口在多数设备上会被识别为点对点或者非广播多路访问。点对点类型不会做 DR/BDR 选举,直接建邻居;非广播类型不做多播,需要手工指定邻居。而 MGRE 的隧道接口本质上是多路访问的,如果用点对点类型,Hub 会认为每个邻居都是独立的一条链路,行为虽然能跑但和预期不符;如果用非广播类型,多播报文发不出去,邻居起不来。

所以我在两边都显式配了ip ospf network broadcast,把它当成一个广播型的以太网段来处理。这样 Hub 和所有分支在同一个网段里,做正常的 DR/BDR 选举,多播 Hello 报文能正常泛洪。

这里有个连带问题:广播型网络需要选 DR,而 DR 的角色应该由 Hub 承担——Hub 是所有分支的共同邻居,让它当 DR 能保证 LSA 泛洪的效率。所以 Hub 的隧道接口配ip ospf priority 255(最高优先级,确保必选上),分支配ip ospf priority 0(不参与选举,永远不当 DR)。这个细节如果不处理,可能某天某个分支因为优先级相同、Router ID 更大而抢到了 DR,然后那台分支重启一次,整个隧道的邻居关系就要重新收敛一遍。生产环境里这种“随机性”的故障是最难查的。

3.2 中心节点的多播复制与 DR 角色安排

除了网络类型和优先级,Hub 上还有一个隐含配置:多播复制。前面提到ip nhrp map multicast dynamic是让 Hub 把多播报文复制给所有注册的分支。这一行如果漏了,现象非常典型——OSPF 邻居状态一直卡在 INIT 或者根本看不到邻居,因为 Hub 发的 Hello 报文没有送到任何分支手里。

我遇到过另一类现象:Hub 能收到分支的 Hello,分支收不到 Hub 的,因为分支侧的多播映射没配(ip nhrp map multicast 203.0.113.1那一条)。这种“单向通”的情况很容易让人怀疑是防火墙或者 ACL 拦了,实际上是 NHRP 的多播映射不对称导致的。判断方法是在 Hub 上开调试看有没有收到 Hello,收到了但邻居起不来,问题就在回复方向。

配置路由协议的部分,Hub 上大致是这样:

router ospf 1 router-id 10.255.255.1 network 172.16.10.0 0.0.0.255 area 0 network 192.168.10.0 0.0.0.255 area 0

分支类似,把自己的隧道网段和业务网段宣告进去。注意别用network 10.0.0.0 0.255.255.255这种大范围的宣告,实验环境里容易把不该宣告的接口也带进去,导致莫名其妙的邻居关系。精确宣告是哪几段就写哪几段,这是好习惯。

3.3 OSPF 邻居建立与分支间路径切换的验证

配置完成之后,在 Hub 上show ip ospf neighbor应该看到三条 FULL 状态的邻居。如果状态不是 FULL,后面第三章的排查表会详细说。

邻居起到 FULL 之后,在 Spoke1 上看路由表,应该能看到 Spoke2、Spoke3 的业务网段,下一跳是 Hub 的隧道地址。这时候从 Spoke1 ping Spoke2 的业务网段,第一次 ping 可能会丢一两个包——这是正常的,因为 NHRP 需要做一次地址解析,解析完成后建立的直连路径才生效。

验证直连是否真的建立,方法是在 Spoke1 上再看一次 NHRP 表:

show ip nhrp

如果出现了一条目标为 172.16.10.12、真实地址为 203.0.113.12 的记录,说明直连路径已经建立,后续 Spoke1 到 Spoke2 的流量不再经过 Hub。这个验证步骤非常关键,很多人做完实验以为通了就行,其实流量还在绕行 Hub,方案的核心优势根本没体现出来。

如果这条记录一直不出现,检查两件事:一是 Spoke1 到 Spoke2 的路由下一跳是不是 Spoke2 的隧道地址(如果是 Hub 的隧道地址,说明 Hub 做了 next-hop-self,需要去掉);二是 Hub 有没有配置阻止 NHRP 重定向的策略。这两个原因占了绝大多数。

3.4 路由协议适配的对照表

不同路由协议在 MGRE 上跑的表现差别很大,我把踩过的整理成表:

协议在 MGRE 上的主要问题处理方式
OSPF广播型需选 DR;MTU 不一致导致邻居卡 EXSTART显式设网络类型、Hub 优先级 255、统一 MTU
距离矢量类协议水平分割导致 Hub 学到的分支路由不回传给其他分支在隧道接口关闭水平分割
静态路由分支新增需在 Hub 上逐条加仅在极小型场景使用,否则维护成本过高

水平分割这个问题特别值得说一句。距离矢量协议的设计初衷是防止环路,规则是“从一个接口学到的路由不再从这个接口发出去”。在点对点链路上这个规则是合理的,但在 MGRE 这种一个接口连多个邻居的场景下,Hub 从 Spoke1 学到的路由不会从同一个隧道接口发给 Spoke2,结果就是分支之间互相学不到对方的路由。这个现象容易被误判为“路由协议没配好”,实际上是协议默认行为和多路访问场景不匹配。解决办法是关闭隧道接口的水平分割,或者在 Hub 上配置路由重分发,让路由以另一条路径进入。前者更直接。

4. 故障排查实录:这套实验真正耗时间的地方

配置敲完只是开始,真正花时间的是排查。这一章我把这套实验里遇到的典型故障按“现象—原因—处理”整理出来,大部分是我自己或者身边的人真实踩过的。

4.1 隧道起不来的分层排查法

隧道接口显示 down,或者 up 了但状态异常,我的排查顺序是固定的四层:

第一层,物理层和传输层。tunnel source指定的接口是不是 up、地址通不通。最常见的错误是把tunnel source写成了一个 down 掉的物理接口,或者写的是一个不可达的 LoopBack 地址,因为 LoopBack 本身是 up 的但路由上没有去往它的路径,实际上从分支根本到不了。

第二层,模式层。Hub 上必须tunnel mode gre multipoint,分支上也一样。很多人只改了 Hub 忘了分支,或者反过来,结果一边是多点模式一边是点对点模式,协议行为对不上,注册永远失败。

第三层,NHRP 层。network-id 一致、认证密钥一致、Hub 的隧道地址在分支上能解析到。这三项任何一个不对,注册都不会成功。检查方法是 Hub 上看show ip nhrp有没有记录、分支上看show ip nhrp nhs状态是不是 reachable。

第四层,协议层。隧道通了、NHRP 注册了,但路由邻居起不来。这时候查的是多播映射、网络类型、MTU 这几个因素。

这个分层顺序的好处是每一步都有明确的验证点,不需要凭猜测乱试。我见过很多人在第三层出问题的时候去改第四层的配置,越改越乱,最后把能通的部分也改坏了。

4.2 NHRP 注册失败的四类原因

注册失败是这套实验里最高频的问题,我把它归纳成四类:

第一类是标识不一致。network-id或者认证密钥对不上,静默失败,日志里可能什么提示都没有。这种情况只能靠人工核对,没有捷径。

第二类是源地址不可达。分支的tunnel source用的是 LoopBack,而 Hub 的路由表里没有去往这个 LoopBack 的路由,注册报文能发出去但回不来。解决方法是把隧道源改成物理接口地址,或者在 Hub 上补路由。这也是我前面说“底层先 ping 通”的原因。

第三类是 NAT 环境。分支在地址转换设备后面时,Hub 学到的真实地址是转换后的地址,如果转换设备对 GRE 协议(IP 协议号 47)放行不完整,注册报文能出去、回应回不来。这种现象的表现是分支显示注册中但永远不成功,用抓包工具在转换设备两侧同时抓,能明显看到单向有包。处理办法是在转换设备上放行对应的协议,并把隧道建立的策略理清楚。

第四类是地址冲突。多个分支配置了相同的隧道地址,Hub 上后注册的会覆盖前面的,表现为“某个分支突然不通”。实验环境里手工配地址特别容易出现这种问题,改地址之前先show ip nhrp看一眼有没有重复。

4.3 邻居卡在 EXSTART / 路由不生效

OSPF 邻居状态卡在 EXSTART 或者 EXCHANGE,是 MTU 不匹配的经典表现。原因是 OSPF 在交换数据库描述报文时会协商 MTU,两边不一致就停在那里。解决办法是统一两端的 MTU,或者用ip ospf mtu-ignore忽略检查。

后一种做法我一般不建议,因为忽略检查并没有真正解决 MTU 问题,只是把问题往后推了——邻居能起来,但大包还是会丢。正确做法是两头把tunnel mtu配成一样的值,一起往下调。

还有一种路由不生效的情况是宣告的网段写错了。比如network 192.168.11.0 0.0.0.255 area 0写成了network 192.168.11.0 0.0.0.0,只宣告了一个地址,结果业务网段里的其他地址学不到。这种错靠看配置不容易发现,要靠看show ip ospf interface确认哪个接口进了 OSPF、show ip route确认对面学到了几条。

4.4 常见问题速查表

现象可能原因快速验证
隧道接口 down隧道源接口 down 或地址不可达检查源接口状态和路由表
隧道 up 但 NHRP 无记录network-id 或认证密钥不一致对比两端配置
注册中但永不成功转换设备未放行 GRE 协议号 47两侧同时抓包
OSPF 无邻居缺多播映射配置检查 map multicast
邻居卡 EXSTART两端 MTU 不一致统一 tunnel mtu
分支间路由不通水平分割或 next-hop-self检查接口配置
小包通大包不通MTU 设置过大df-bit ping 二分法
Hub 重启后部分分支失联分支地址变化未重新注册等待注册超时重试

这张表里最后一行值得单独说。分支地址变化后,Hub 上的旧表项不会立刻失效,要等注册超时才更新,这段时间内流量会打到失效地址上,表现为“偶尔断”。生产环境里要把注册超时时间调短一点,或者在分支上配一个探测机制,让它主动重新注册。

5. 影响范围与加固延展

这套方案跑通之后,我花了一点时间评估它的影响范围和潜在风险,这部分内容在实验报告里通常不写,但对实际落地很关键。

5.1 中心节点是唯一的故障放大点

MGRE 的星型物理结构决定了一件事:Hub 挂了,所有分支互访全部中断,包括原本直连的分支之间——因为它们最初的地址解析依赖 Hub。这是个架构层面的单点,只能靠 Hub 做冗余来缓解,比如部署两台 Hub、所有分支同时注册到两台,或者用某种网关冗余协议。实验环境里不做这个,但心里要清楚它的存在。

另一个影响是带宽。虽然分支互访可以直连,但初始流量、广播报文、路由更新全部要经过 Hub,Hub 的出口带宽是这套方案的上限。分支数量一多,Hub 上的多播复制开销会明显上升——每一个路由协议报文都要复制 N 份发出去,N 大了以后 CPU 和带宽都会被吃掉一部分。规划的时候按分支数乘以单条隧道开销来估算,别等到跑满了才发现。

还有一个容易忽略的影响是故障域。MGRE 把所有分支放进同一个隧道网段,等于把所有分支放进了同一个广播域。某个分支的路由协议配错、发出大量异常报文,会影响整个隧道域内所有设备。点对点隧道没有这个问题,因为每对设备是隔离的。所以在 MGRE 上要格外注意路由协议的过滤和认证,把异常隔离在单个分支内。

5.2 从实验到生产的几个加固动作

实验环境里跑通和能上生产是两回事,中间至少差这么几步:

第一步是加加密。在隧道配置外面套一层 IPSec,让 GRE 报文在传输网里加密传输。加完之后 MTU 要重新测,通常会比原来少 50 到 70 字节,tunnel mtu和adjust-mss都要跟着降。

第二步是加认证和过滤。NHRP 的明文认证只能防误接入,防护强度有限。生产环境要在隧道接口上配访问控制,限制哪些源地址能通过隧道访问哪些业务网段。我一般会在 Hub 上针对每个分支的隧道地址配置精确的过滤规则,而不是一刀切全放通。全放通的后果是任何一个分支被攻破,整个内网就暴露了。

第三步是监控。至少要监控三类指标:NHRP 注册状态(有没有分支掉线)、隧道接口的流量和错误计数、路由邻居的状态变化。前两个靠轮询就能做,第三个建议配合日志告警。这套实验里我曾经有过一个分支因为运营商线路问题静默掉线两天,直到业务方反馈才发现,原因是只看了接口 up/down 状态,隧道接口因为底层路由还在所以一直显示 up。

第四步是文档。这套配置里最容易出问题的是网络标识、认证密钥、地址段这些“约定类”参数,散落在各个设备上。集中记录下来,新增分支的时候直接对照填,比现场翻配置可靠得多。

5.3 我个人在这套实验里摔过的跟头

最后说几个纯经验性的东西。

第一个是配置顺序。我一开始图快,把隧道、NHRP、OSPF、加密一次性全配上,结果不通的时候完全不知道是哪一层的问题,只能一层层往下剥,剥到最后发现是最基础的 network-id 打错了。后来我改成严格的四步验证法,每步通过才进下一步,总耗时反而比一次性配完再排查要短。

第二个是地址规划。隧道的 /24 网段里,我把 Hub 配成 .1,分支从 .11 开始,中间留出空档。有次在别的实验里随手用了 .2、.3,结果和另一个环境的地址段冲突,路由表里出现重叠,排查了很久。现在养成的习惯是所有实验环境的地址段都做记录,隧道段和业务段严格隔离。

第三个是tunnel mtu的取值。我最初没配这一项,默认跟着物理接口走 1500,结果 SSH 登录正常但文件传输卡死,抓包才看到大包全被丢弃。后来固定成 1400,再套加密降到 1360,一直很稳。这个值不用追求“最优”,留足余量比榨干带宽重要得多。

第四个是多播映射这一行。我在 Hub 上配了,分支上忘了,结果 Hub 能看到分支,分支看不到 Hub,OSPF 邻居卡在 INIT 一整天。后来我给自己定了个规矩:凡是带map multicast的命令,两边都要检查一遍,宁可多配也不要漏配。

这套实验做到最后,我最大的体会是:MGRE 本身不难,难的是它把一个原本点对点的确定性问题,变成了一个多对多的、带状态缓存的动态问题。隧道能不能通是显性问题,看接口状态就知道;NHRP 的映射是否及时、路由的下一跳是否正确、多播有没有丢,全是隐性问题,只能靠主动验证。所以我现在做这类实验,配置完必做的三件事是:看 NHRP 表、看路由下一跳、用带 df-bit 的大包 ping 一遍,这三件事过了,才算真的通了。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进