☰
GRE隧道实战:从MTU故障到GRE over IPsec的运维避坑指南
2026/10/18 5:36:23 网站建设 项目流程

1. 从一个"看起来通了但实际没通"的故障说起

GRE,全称Generic Routing Encapsulation,通用路由封装。这名字听起来很学术,但如果你做过网络运维,大概率在某个深夜被它折腾过。我第一次接触GRE是在一个跨机房互联的项目里,两个机房的私网需要互通,中间隔着一段运营商网络。当时想得很简单:两边各起一个GRE隧道,把私网路由指过去,收工。结果隧道状态显示up,接口能ping通,但业务流量就是过不去。排查了整整一个下午才发现,是MTU的问题——GRE封装会额外增加24字节的开销,加上外层IP头20字节,总共多出44字节,导致大包被丢弃,小包正常。这就是GRE最典型的"看起来通了但实际没通"。

所以这篇内容我想聊的不是教科书上那些定义,而是GRE隧道在实际工程中到底怎么用、为什么这么用、以及那些只有踩过坑才知道的细节。适合已经了解基本网络概念、需要把GRE真正落地到项目里的运维和网络工程师。如果你只是想知道GRE是什么,网上有大把定义;但如果你想搞清楚GRE在什么场景下比IPsec更合适、怎么配才能稳、出了问题从哪查起,那接下来的内容应该对你有用。

GRE的本质其实很朴素:它就是一种把一种协议的数据包套在另一种协议的数据包里的方法。你可以把它想象成快递里的"箱中箱"——你要寄一个形状不规则的物品(内层原始数据包),直接寄不好寄,于是先装进一个小箱子(GRE封装),再把小箱子放进标准的大纸箱(外层IP包),这样任何快递网络都能运送。收件人拆开大纸箱,取出小箱子,再打开小箱子拿到真正的物品。这个"套娃"的过程就是隧道。

2. GRE封装结构里那些容易被忽略的字段

2.1 外层IP头与GRE头的分工

要理解GRE的行为,必须先把它的封装结构拆开看。一个完整的GRE隧道包由三部分组成:外层IP头、GRE头、内层原始数据包。

外层IP头的源地址和目的地址分别是隧道两端接口的地址,这是隧道能建立的基础。协议号字段填47,标识这是一个GRE包。很多人配完隧道后不检查这个字段,但如果中间有防火墙,协议号47被拦了,隧道就起不来——而且因为GRE本身没有认证机制,你甚至不会收到任何报错,只能看到隧道一直down。

GRE头本身的结构值得细看。标志位和版本字段通常为0,但如果你用到GRE的扩展能力(比如带Key或带序列号),这里就会有值。协议类型字段标识内层承载的是什么协议,0x0800代表IPv4,0x86DD代表IPv6,0x8847代表MPLS。这个字段决定了隧道"运什么货"。

2.2 Key字段与序列号的实际用途

Key字段是一个4字节的标识符,可以理解为隧道的"门牌号"。它的实际价值在于:当多个GRE隧道终止在同一对设备上时,用Key来区分不同的隧道。我见过一个场景,两台核心设备之间需要跑三条不同业务的GRE隧道,如果不加Key,接收端无法区分哪个包属于哪条隧道,配置就会冲突。加上Key之后,每条隧道有独立的标识,问题解决。

序列号字段用于保证包的顺序。默认情况下GRE不启用序列号,因为大多数内层协议(如TCP)自己有重传和排序机制。但在承载某些对顺序敏感的非IP协议时,序列号就有意义了。不过要注意,启用序列号会增加处理开销,而且如果中间路径存在乱序,序列号机制反而可能引入额外延迟。我的建议是:除非有明确需求,否则不要开。

校验和字段同理。GRE头里的校验和只校验GRE头和内层包,不包括外层IP头。启用它会增加每包的计算成本,在高速链路上可能成为瓶颈。实际项目中我基本不启用GRE校验和,而是依赖外层IP头的校验和以及内层协议自身的校验机制。

2.3 MTU问题:GRE隧道最大的隐形杀手

回到开头那个故障。GRE封装增加的开销具体是:外层IP头20字节 + GRE头4字节(基础情况下)= 24字节。如果外层还跑了IPsec,那开销更大。标准以太网MTU是1500字节,减去24字节,隧道内层能承载的最大包就是1476字节。

问题在于,很多应用和协议默认使用1500字节的包,而且设置了"禁止分片"位。当这样的包进入GRE隧道时,设备发现加上封装头后超过了出口MTU,但又不能分片,只能丢弃。表现就是:ping小包正常,ping大包失败;网页能打开但图片加载不全;SSH能连上但一传文件就断。

解决方案有三种。第一种是调整隧道接口的MTU和TCP MSS。把隧道接口MTU设为1476,同时用ip tcp adjust-mss 1436让经过隧道的TCP连接协商更小的MSS。1436的计算方式是:1476减去20字节TCP头再减去20字节IP头。第二种是在隧道两端启用路径MTU发现,但这依赖中间网络配合,实际环境中经常不靠谱。第三种是直接在外层网络上把MTU调大,比如启用巨帧,但这需要整条路径都支持,跨运营商场景基本不可行。

我个人的经验是:不管三七二十一,配GRE隧道时先把MTU和MSS调了。这个动作花不了两分钟,但能省掉后面可能几个小时的排查。

3. 什么时候该用GRE,什么时候该换方案

3.1 GRE与IPsec的分工逻辑

很多人会问:既然IPsec也能建隧道,为什么还要用GRE?答案在于两者解决的问题不同。IPsec的核心是安全——加密、认证、防篡改。GRE的核心是封装——把一种协议套进另一种协议里。它们不是竞争关系,而是互补关系。

GRE本身没有任何加密能力,所有数据明文传输。这意味着如果你用纯GRE隧道跑敏感数据,中间任何一跳都能看到内容。所以纯GRE只适合两种场景:一是中间网络本身可信(比如同一个数据中心内部的不同网段),二是GRE只作为封装层,上面再跑IPsec来加密。

IPsec的问题在于它通常只支持单播IP流量,而且配置复杂,不同厂商设备之间的互通性经常出问题。GRE则简单得多,而且能承载组播、广播、非IP协议。所以经典组合是:GRE负责封装和承载多协议流量,IPsec负责加密。这就是常说的GRE over IPsec。

3.2 动态路由协议穿越GRE的实战价值

GRE最实用的场景之一,是让动态路由协议穿越不支持它的网络。比如两个站点之间隔着运营商网络,你想跑OSPF让两边路由自动学习。但OSPF使用组播地址224.0.0.5,运营商网络通常不转发组播。这时候GRE隧道就派上用场了:隧道接口是一个点对点的逻辑链路,OSPF可以在这个接口上正常跑,组播包被GRE封装成单播包,顺利穿过运营商网络。

配置上,隧道两端各起一个Tunnel接口,配上网段地址,然后在OSPF进程里把Tunnel接口的网段宣告出去。隧道建立后,OSPF邻居关系会在Tunnel接口上形成,两边路由自动同步。这个方案我在多个跨地域组网项目里用过,稳定可靠。

但要注意一个细节:OSPF在Tunnel接口上的邻居关系建立依赖于隧道本身的可达性。如果隧道底层网络断了,Tunnel接口会down,OSPF邻居也会断。这其实是好事——避免了路由黑洞。但如果你在隧道上还跑了静态路由指向对端,就要小心递归路由的问题:静态路由指向Tunnel接口,Tunnel接口的源地址又依赖底层网络路由,如果底层路由丢失,整个链路就断了。

3.3 组播与广播流量穿越的注意事项

GRE能承载组播和广播,这是它比IPsec强的地方。但实际用的时候有几个坑。第一,GRE隧道默认不转发广播,需要在隧道接口上显式开启广播转发。第二,组播流量进入隧道后,外层是单播,内层是组播,接收端解封装后需要正确还原组播包。如果两端组播配置不一致,流量就丢了。第三,广播风暴的风险——如果隧道一端有广播风暴,会通过隧道传到另一端。所以生产环境里,我通常会在隧道接口上做广播抑制或风暴控制。

4. 从零搭建一条GRE隧道的完整操作链路

4.1 基础配置:两端接口与隧道参数

假设有两台设备,A端公网地址是198.51.100.1,私网网段是10.1.1.0/24;B端公网地址是203.0.113.1,私网网段是10.2.2.0/24。目标是通过GRE隧道让两个私网互通。

A端配置:

interface Tunnel0 ip address 172.16.0.1 255.255.255.252 tunnel source 198.51.100.1 tunnel destination 203.0.113.1 tunnel mode gre ip ip mtu 1476 ip tcp adjust-mss 1436 ! interface GigabitEthernet0/0 ip address 198.51.100.1 255.255.255.0 ! interface GigabitEthernet0/1 ip address 10.1.1.1 255.255.255.0 ! ip route 10.2.2.0 255.255.255.0 Tunnel0

B端配置对称:

interface Tunnel0 ip address 172.16.0.2 255.255.255.252 tunnel source 203.0.113.1 tunnel destination 198.51.100.1 tunnel mode gre ip ip mtu 1476 ip tcp adjust-mss 1436 ! interface GigabitEthernet0/0 ip address 203.0.113.1 255.255.255.0 ! interface GigabitEthernet0/1 ip address 10.2.2.1 255.255.255.0 ! ip route 10.1.1.0 255.255.255.0 Tunnel0

这里有几个关键点。隧道接口的地址用了172.16.0.0/30这个私网网段,只用了两个可用地址,不浪费。tunnel source和destination分别指向对方的公网地址,这是隧道能建立的前提。ip mtu和ip tcp adjust-mss是必须加的,原因前面已经说过。静态路由把对端私网指向Tunnel接口,这样流量才会进入隧道。

4.2 验证隧道状态的三层检查法

配完之后别急着收工,按三层顺序检查。

第一层,物理和底层可达性。在A端ping B端的公网地址203.0.113.1,必须通。如果不通,隧道肯定起不来,先查底层路由。

第二层,隧道接口状态。show interface Tunnel0看接口是否up,协议是否up。如果接口up但协议down,通常是tunnel destination不可达或者中间有防火墙拦了协议47。如果接口down,检查tunnel source地址是否本地有效地址。

第三层,隧道内层连通性。在A端ping 172.16.0.2,这是B端隧道接口地址。通了说明隧道本身工作正常。然后再ping 10.2.2.1,这是B端私网接口地址。如果隧道内层通但私网不通,检查静态路由和B端的回程路由。

我习惯用show interface Tunnel0的输出里看几个关键计数:packets input/output、CRC错误、drops。如果input有包但output没包,可能是路由问题;如果有drops且数值持续增长,大概率是MTU问题。

4.3 隧道建立不起来的排查顺序

隧道起不来是最常见的问题。我的排查顺序是这样的:

先确认两端tunnel source和destination是否互为对方的地址。这个听起来很基础,但我确实见过配错地址的情况——A端destination写了B端的私网地址而不是公网地址。

再确认中间网络是否放行了协议47。GRE没有端口概念,防火墙只能基于协议号过滤。如果中间有防火墙,需要放行IP协议47。可以用telnet或traceroute辅助判断,但最直接的方法是在两端抓包,看GRE包有没有发出去、有没有收到。

然后检查路由。tunnel destination地址必须在本地路由表里有明确的路由,而且不能是默认路由指向Tunnel接口本身——这会造成递归路由,隧道永远起不来。可以用show ip route 203.0.113.1确认走的是物理接口而不是Tunnel接口。

最后检查ACL。如果设备上有ACL应用在物理接口的入方向,可能会拦掉GRE包。GRE包的源地址是对方公网地址,目的地址是本地公网地址,协议47。确认ACL里有permit gre any any或者更精确的规则。

5. GRE over IPsec:加密与封装的正确组合方式

5.1 为什么不能直接用IPsec承载动态路由

前面提到GRE over IPsec是经典组合,但为什么不能直接用IPsec而要套一层GRE?核心原因是IPsec的ACL匹配逻辑。IPsec的感兴趣流ACL通常匹配的是源和目的IP地址对,它只对匹配的流量做加密。如果你想让OSPF穿越IPsec,就需要在ACL里放行OSPF的组播地址224.0.0.5。但IPsec的加密隧道是点对点的,组播流量进入IPsec后无法正确映射到隧道上。而且IPsec的ACL是单向的,需要两端镜像配置,维护起来很麻烦。

GRE over IPsec的做法是:先建GRE隧道,让所有需要穿越的流量(包括OSPF)都走GRE隧道;然后用IPsec保护GRE隧道本身。IPsec的ACL只需要匹配GRE包的源和目的地址(即两端公网地址),协议47。这样配置简单,而且所有进入GRE隧道的流量自动被加密。

5.2 配置顺序与关键参数

配置顺序很重要:先配GRE隧道并验证隧道内层能通,再配IPsec保护GRE。如果反过来,IPsec配好了但GRE没通,排查起来会很混乱。

IPsec部分的配置要点:IKE阶段用预共享密钥或证书,IPsec阶段用ESP加密和认证。ACL匹配协议47,源和目的分别是两端公网地址。应用crypto map到物理接口。这些是标准IPsec配置,不展开细说。

关键参数是IPsec的MTU处理。GRE已经增加了24字节开销,IPsec的ESP头尾又增加约50-73字节(取决于加密和认证算法)。所以隧道内层实际可用的MTU可能只有1400左右。这时候ip mtu和ip tcp adjust-mss要相应调小。我通常会把隧道接口MTU设为1400,MSS设为1360,留足余量。

5.3 加密后性能下降的实测数据

GRE over IPsec的性能开销主要来自加密和封装。在软件转发平台上,启用IPsec后吞吐量可能下降50%以上。硬件加速卡能大幅改善,但不同厂商的实现差异很大。我实测过一组数据:纯GRE隧道在千兆链路上能跑到线速,加上IPsec后降到400-600Mbps,具体取决于包大小和加密算法。AES-256比AES-128慢约15-20%,SHA-256比SHA-1慢约10%。如果性能是瓶颈,可以考虑用AES-128和SHA-1,但安全性会降低,需要根据实际威胁模型权衡。

6. 那些只有踩过才知道的GRE运维细节

6.1 隧道震荡与路由翻动

GRE隧道本身没有保活机制。如果中间网络出现闪断,隧道接口可能不会立即down,但实际流量已经不通了。如果隧道上跑了OSPF,OSPF的hello超时后邻居会断,路由翻动,然后隧道恢复后OSPF重新收敛。这个过程可能造成几十秒的业务中断。

解决方案是启用GRE的keepalive。配置keepalive 10 3表示每10秒发一次保活包,连续3次收不到就认为隧道down。这样隧道接口能快速感知底层故障,触发路由切换。但要注意,keepalive包本身也走隧道,如果底层完全断了,keepalive也发不出去,所以它只能检测部分故障场景。

另一个方案是在隧道上跑BFD。BFD的检测间隔可以做到毫秒级,比keepalive快得多。但BFD需要两端设备都支持,而且配置稍复杂。我的建议是:如果业务对中断时间敏感,上BFD;如果只是普通互联,keepalive够用。

6.2 多隧道场景下的Key与源地址选择

当一台设备上有多条GRE隧道时,Key字段就变得重要了。假设一台设备同时连接三个分支,每条隧道用不同的Key。接收端根据Key值把包分发给对应的隧道接口。如果不配Key,所有隧道共用同一个源和目的地址对,接收端无法区分,配置会报错。

另一个细节是tunnel source的选择。如果设备有多个公网地址,tunnel source指定哪个地址,隧道就用哪个地址作为外层源地址。这个地址必须是对方能路由到的地址。我见过一个案例:设备有两个公网地址,一个用于业务,一个用于管理。tunnel source配了管理地址,但对方没有到管理地址的路由,隧道起不来。后来改成业务地址就好了。

6.3 GRE与NAT的兼容性问题

GRE和NAT一起用的时候要特别小心。NAT设备通常只处理TCP和UDP,对协议47的GRE包可能直接丢弃或者无法正确转换。如果GRE隧道的一端在NAT后面,隧道可能起不来。

解决方案有两种。一是用GRE的NAT穿越能力,但这需要两端设备都支持,而且配置复杂。二是把GRE隧道的一端放在有公网地址的设备上,避免NAT。如果实在避不开,可以考虑用IPsec的NAT穿越功能来替代纯GRE,因为IPsec over UDP可以穿透NAT。

我在一个项目里遇到过这种情况:分支机构的出口设备做了NAT,总部想和分支建GRE隧道。试了各种配置都不行,最后改成在分支设备上配一条静态NAT,把GRE流量映射到内网设备,才解决问题。但这个方案要求分支有固定公网地址,动态地址场景下不可行。

6.4 隧道接口的ACL与安全加固

GRE隧道默认不加密,所以隧道接口上的ACL很重要。我通常会在隧道接口的入方向配ACL,只允许必要的流量进入。比如只允许对端私网网段访问本地私网网段,其他一律拒绝。这样即使隧道被利用,攻击面也有限。

另外,隧道接口不要配公网地址,用私网地址即可。隧道接口地址只用于隧道内层通信和路由协议,不需要对外暴露。如果隧道上跑了动态路由,还要考虑路由认证,防止恶意路由注入。

还有一个容易忽略的点:GRE隧道会转发广播。如果一端有ARP广播风暴,会通过隧道传到另一端。所以隧道接口上最好配广播抑制,或者用ACL限制广播流量。

7. 从故障现象反推GRE问题的排查思路

7.1 隧道up但业务不通的四种可能

隧道接口显示up,但业务流量不通,这是最让人头疼的情况。根据我的经验,可能的原因有四种。

第一种是MTU问题。表现是小包通、大包不通。验证方法是用不同大小的ping包测试,比如ping 10.2.2.1 size 1400和ping 10.2.2.1 size 1500。如果1400通、1500不通,基本可以确定是MTU。解决方案是调小隧道接口MTU和TCP MSS。

第二种是路由问题。隧道内层能ping通对端隧道接口地址,但ping不通对端私网地址。检查两端的路由表,确认对端私网网段指向Tunnel接口。同时检查是否有更精确的路由覆盖了隧道路由。

第三种是ACL拦截。隧道接口或物理接口上的ACL可能拦掉了业务流量。检查ACL的匹配顺序和规则内容。特别注意隐式deny any,如果ACL最后没有permit规则,所有不匹配的流量都会被丢弃。

第四种是非对称路由。去程走隧道,回程走其他路径。这种情况在有多条路径的网络里常见。表现是ping通但TCP连接建立失败,因为TCP握手需要双向通。检查两端的路由表,确保去程和回程路径一致。

7.2 抓包分析:在哪个接口抓、看什么字段

抓包是排查GRE问题的终极手段。抓包位置很关键:在物理接口抓包能看到GRE封装后的包,在隧道接口抓包能看到解封装后的内层包。

在物理接口抓包时,看外层IP头的源和目的地址是否正确,协议号是否为47。如果看不到GRE包,说明流量根本没进隧道,问题在路由或ACL。如果看到GRE包但对方没收到,问题在中间网络。

在隧道接口抓包时,看内层包的源和目的地址,以及TCP/UDP端口。如果内层包正常但业务不通,问题可能在应用层或MTU。

我常用的抓包命令是tcpdump -i GigabitEthernet0/0 -n -v 'proto 47',只抓GRE包,减少干扰。分析时重点看:包的源和目的地址、包的大小、是否有分片标志、序列号是否连续。

7.3 性能问题的定位:是GRE的锅还是底层网络的锅

GRE隧道的性能问题不一定都是GRE本身造成的。定位方法很简单:在隧道两端做吞吐量测试,对比隧道内和隧道外的结果。如果隧道外能跑满带宽,隧道内只有一半,那可能是GRE封装解封装的开销,也可能是MTU问题导致的分片重传。

另一个方法是看CPU利用率。软件转发的GRE隧道会消耗CPU,如果CPU跑满了,吞吐量就上不去。这时候需要考虑硬件加速或者换用支持硬件GRE转发的平台。

还有一个容易被忽略的点:GRE隧道的流量会经过物理接口,如果物理接口本身有拥塞或错误,隧道性能也会受影响。检查物理接口的错包计数和带宽利用率,排除底层问题。

8. 我个人在GRE运维中积累的几条实用原则

第一条原则:配GRE必调MTU和MSS。不管你觉得有没有必要,先调了再说。这个动作的成本极低,但能避免大量诡异问题。

第二条原则:隧道接口地址用/30或/31。只给隧道两端各一个地址,不浪费地址空间。隧道接口不需要广播地址,/31在点对点链路上完全够用。

第三条原则:隧道上跑路由协议时,一定要配路由认证。GRE不加密,路由协议如果不认证,容易被恶意注入。OSPF用MD5或SHA认证,BGP用TCP MD5或更高级的认证。

第四条原则:生产环境的GRE隧道必须配监控。监控隧道接口的状态、流量、错包计数。隧道down了要告警,流量异常也要告警。我见过隧道断了三天没人发现的情况,就是因为没有监控。

第五条原则:能用IPsec保护就用IPsec保护。纯GRE只适合完全可信的网络环境。跨公网的GRE隧道,不管业务是否敏感,都建议套一层IPsec。成本不高,但安全性提升明显。

最后分享一个排查小技巧:当你怀疑GRE隧道有问题但不确定时,在两端同时抓包,对比发出的包和收到的包。如果A端发出了100个GRE包,B端只收到80个,说明中间网络丢了20个。如果B端收到了100个但解封装后只有80个,说明GRE处理有问题。这个方法能快速定位问题出在传输路径还是隧道端点。

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

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

立即咨询