GRE隧道从入门到实战:原理、配置与常见问题排查

发布时间:2026/10/18 18:24:56
GRE隧道从入门到实战:原理、配置与常见问题排查
1. 从一个真实需求说起为什么还要折腾GRE隧道第一次接触GRE隧道是在一个跨机房互联的项目里。当时手头有两套环境一套跑着核心业务另一套是新建的测试集群两边分属不同的网段中间隔着好几层路由设备。最直接的想法是加静态路由但问题是中间那些设备不归我们管改配置要走审批流程周期长不说还不一定能批下来。后来团队里一位老哥提了一句“要不套个GRE隧道试试”就这样我第一次认真研究起了这个看起来有点“古老”的技术。GRE全称Generic Routing Encapsulation中文一般叫通用路由封装。它的核心思路其实特别朴素把一种协议的数据包整个打包进另一种协议的数据包里然后在两端之间建一条逻辑上的点对点通道。你可以把它想象成快递——你要寄一个形状奇怪的物品直接寄不好寄那就先装进一个标准纸箱到了目的地再拆箱取出原物。GRE干的就是这个“装箱”和“拆箱”的活。这个技术能解决什么问题最典型的就是跨网段通信、多协议传输、以及在不改变现有路由架构的前提下打通两个孤立的网络。适合谁来参考网络运维、系统集成、云计算运维以及任何需要处理跨机房、跨云、跨网络环境互联的工程师。哪怕你只是偶尔需要把两个不同网段的环境连起来做测试GRE隧道也是一个成本极低、上手极快的选择。但要注意GRE本身不加密也不认证它只管封装和传输。这一点非常关键后面我会反复提到。很多人第一次用GRE踩的坑都和这个特性有关。2. 核心原理拆解GRE到底在干什么2.1 封装与解封装一个包裹的旅程要理解GRE得先理解“封装”这个词。假设你在A网段有一台主机IP是10.1.1.10想访问B网段的10.2.2.20。正常情况下这两个网段之间如果没有路由包是过不去的。GRE的做法是在A网段和B网段各放一台设备可以是路由器、服务器、甚至虚拟机这两台设备之间有一条可达的IP路径比如A端是192.168.1.1B端是192.168.2.1。当10.1.1.10的包到达A端设备时A端设备会把整个原始包当作“载荷”外面再套一层新的IP头新头的源地址是192.168.1.1目的地址是192.168.2.1。这个新包在中间网络里传输时中间设备只看到外层IP根本不知道里面装的是什么。到了B端设备拆掉外层头取出原始包再转发给10.2.2.20。整个过程对两端主机完全透明。这里有一个容易混淆的点GRE隧道本身不负责路由决策它只是提供了一条“通道”。真正的路由还是靠两端的路由表来决定哪些流量走隧道、哪些不走。很多人配置完隧道发现不通第一反应是隧道没建好实际上往往是路由没指对。2.2 GRE头部的结构24字节里藏着什么GRE的头部结构不算复杂但有几个字段值得关注。标准GRE头部是4字节的基础头加上可选的校验和与密钥字段最多8字节。外层IP头是20字节所以一个GRE封装后的包额外开销至少是24字节。这24字节意味着什么如果你的物理链路MTU是1500那么隧道内的有效MTU就变成了1476。这个数字很重要因为很多应用默认按1500发数据一旦走隧道就会触发分片分片又会带来性能下降和丢包风险。我后面会专门讲怎么处理这个问题。GRE头部里有一个Protocol Type字段用来标识里面装的是什么协议。比如0x0800表示IPv40x86DD表示IPv60x8847表示MPLS。这意味着GRE不仅能封装IP还能封装很多其他协议这也是它叫“通用”路由封装的原因。还有一个Key字段可以理解为隧道标识。如果你在同一对端点之间建了多条GRE隧道可以用Key来区分。不过实际项目中我很少见到用Key的场景大多数时候一条隧道就够了。2.3 为什么选GRE而不是其他方案说到隧道技术可选的方案其实不少。IPsec隧道、VXLAN、甚至简单的端口转发都能实现类似的效果。那为什么还要用GRE第一个原因是简单。GRE的配置在主流网络设备上通常就是几行命令在Linux上也就是ip tunnel几条指令的事。相比之下IPsec的配置复杂度要高一个量级涉及IKE协商、加密算法、认证方式等等。如果你只是想要一条通道不需要加密GRE是最省事的。第二个原因是多协议支持。GRE可以封装几乎任何三层协议而IPsec主要针对IP。如果你需要传输非IP流量GRE是更自然的选择。第三个原因是与路由协议配合好。GRE隧道建好后可以在隧道接口上跑OSPF、BGP等动态路由协议让两端路由自动学习。这一点在复杂网络里非常实用。但GRE的缺点也很明显不加密、不认证、没有防重放机制。所以实际项目中如果流量敏感通常会用GRE over IPsec的方式用IPsec来保护GRE隧道。这个组合在很长一段时间里都是跨站点互联的主流方案。3. 实操环境搭建从零建一条GRE隧道3.1 环境规划与参数设计在动手之前先把参数规划清楚。假设我们有两台Linux服务器分别位于不同网段角色物理网卡IP隧道IP所在网段A端192.168.1.10/2410.0.0.1/30192.168.1.0/24B端192.168.2.10/2410.0.0.2/30192.168.2.0/24隧道网段选10.0.0.0/30只用了两个可用地址刚好够点对点使用。这个网段不要和现有网段冲突否则路由会出问题。两端物理IP之间必须可达这是前提。如果中间有防火墙需要放行GRE协议也就是IP协议号47。注意GRE不是基于TCP或UDP的它是独立的IP协议号很多防火墙默认不放行这是新手最容易卡住的地方。3.2 Linux端配置ip tunnel命令详解在A端执行# 加载GRE内核模块 modprobe ip_gre # 创建GRE隧道接口 ip tunnel add gre1 mode gre remote 192.168.2.10 local 192.168.1.10 ttl 255 # 启用接口 ip link set gre1 up # 配置隧道IP ip addr add 10.0.0.1/30 dev gre1B端对称配置modprobe ip_gre ip tunnel add gre1 mode gre remote 192.168.1.10 local 192.168.2.10 ttl 255 ip link set gre1 up ip addr add 10.0.0.2/30 dev gre1配置完后在A端ping 10.0.0.2应该能通。如果不通按这个顺序排查物理IP是否可达、防火墙是否放行协议47、隧道接口是否up、隧道IP是否配置正确。这里有个细节ttl 255是可选的但建议加上。因为GRE封装后外层IP的TTL默认会继承内层如果不设置某些情况下会导致包在中间网络被丢弃。3.3 路由配置让流量走隧道隧道通了只是第一步真正要让业务流量走隧道还得配路由。假设A端背后的网段是172.16.1.0/24B端背后的网段是172.16.2.0/24那么A端需要加ip route add 172.16.2.0/24 dev gre1B端需要加ip route add 172.16.1.0/24 dev gre1如果两端背后的网段比较多逐条加路由很麻烦这时候可以在隧道上跑动态路由协议。比如用OSPF# A端 ip addr add 10.0.0.1/30 dev gre1 # 在gre1和物理网卡上启用OSPF不过OSPF配置涉及更多参数如果只是几条静态路由能搞定的事没必要上动态路由。我的经验是隧道数量少于5条、背后网段少于10个静态路由完全够用而且更可控。3.4 MTU与MSS那个让人头疼的24字节前面提到GRE封装会增加24字节开销。如果物理MTU是1500隧道接口的MTU应该设为1476。在Linux上ip link set gre1 mtu 1476但光设MTU还不够因为TCP握手时协商的MSS是基于物理接口的。如果不对MSS做调整大包还是会分片。解决办法是在隧道接口上做MSS clampingiptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu这条规则的意思是对经过的TCP SYN包把MSS值调整为路径MTU减去头部开销。这样两端主机会协商出合适的MSS避免分片。我踩过的坑有一次隧道通了ping小包没问题但一传大文件就卡死。查了半天才发现是MTU问题。所以记住一句话GRE隧道不通可能是路由问题但GRE隧道“通而不畅”十有八九是MTU问题。4. 进阶玩法GRE over IPsec与多隧道场景4.1 为什么要给GRE套一层IPsecGRE本身不加密这意味着隧道里跑的数据在中间网络上是明文的。如果中间网络不可信比如跨公网那就必须加加密。GRE over IPsec的思路是先用IPsec保护两端物理IP之间的通信然后把GRE隧道建在这条IPsec通道之上。配置顺序很重要先配IPsec确认物理IP之间的加密通道通了再配GRE。如果顺序反了GRE可能先建立起来但IPsec还没就绪导致隧道不稳定。IPsec的配置在不同平台上差异很大这里不展开具体命令但核心参数是两端用相同的预共享密钥或证书、相同的加密算法和哈希算法、感兴趣流设置为两端物理IP之间的GRE流量。4.2 多条GRE隧道并存有时候需要在同一对端点之间建多条隧道比如一条跑业务流量一条跑管理流量。这时候可以用Key字段来区分# 隧道1 ip tunnel add gre1 mode gre remote 192.168.2.10 local 192.168.1.10 key 100 # 隧道2 ip tunnel add gre2 mode gre remote 192.168.2.10 local 192.168.1.10 key 200两端Key要对应否则隧道起不来。不过实际项目中我更倾向于用不同的隧道IP网段来区分而不是依赖Key。因为Key在排查问题时不够直观看接口名和IP更直接。4.3 在云环境里用GRE云环境里用GRE有几个特殊点。第一云平台的安全组或网络ACL需要放行协议47很多云平台默认只放行TCP/UDP/ICMPGRE需要手动加规则。第二云平台的虚拟网络可能对MTU有额外限制比如某些云默认MTU是1450而不是1500这时候隧道MTU要相应调整。第三如果两端都在云上但不同区域中间走的是云厂商的骨干网延迟和丢包率通常比公网好但也要实测确认。我在云上建GRE隧道的经验是先用两台最低配的实例做验证确认协议47能通、MTU合适、路由正确再迁移到生产环境。不要一上来就在生产环境配出了问题影响面太大。5. 常见问题与排查技巧实录5.1 隧道起不来从底层往上查隧道起不来是最常见的问题。我的排查顺序是物理IP能不能ping通如果不通先解决底层可达性。防火墙有没有放行协议47用tcpdump抓包确认。隧道接口状态是不是up用ip link show查看。两端配置是否对称remote和local有没有写反这四步能解决90%的隧道建立问题。剩下10%可能是内核模块没加载、或者云平台有特殊限制。5.2 隧道通了但业务不通路由和MTU是重灾区隧道通了隧道IP能ping通但背后的业务网段不通。这时候先查路由ip route get 172.16.2.10看包是不是走了隧道接口。如果走了物理接口说明路由配错了。如果走了隧道接口但还不通检查对端有没有回程路由。如果路由没问题再查MTU。用ping大包测试ping -M do -s 1472 10.0.0.21472加上28字节的IP和ICMP头正好是1500。如果这个不通但小包通就是MTU问题。5.3 性能问题GRE的 overhead 到底有多大影响GRE封装会增加24字节这意味着同样的物理带宽下有效吞吐会下降。粗略估算如果物理MTU是1500隧道MTU是1476那么有效载荷比例是1476/1500大约98.4%。也就是说100Mbps的链路跑GRE隧道后有效带宽大约是98.4Mbps。这个损耗不算大但如果是小包场景比如VoIP头部开销占比会更高。另外GRE封装和解封装需要CPU参与如果流量很大可能成为瓶颈。在Linux上可以开启GRO/GSO等卸载功能来减轻CPU压力。不过这些是优化手段不是必须的。5.4 常见问题速查表现象可能原因排查方法隧道接口起不来物理IP不可达ping对端物理IP隧道接口起不来防火墙拦截协议47tcpdump抓包隧道通了但业务不通路由未指向隧道ip route get隧道通了但业务不通对端无回程路由检查对端路由表小包通大包不通MTU问题ping -M do -s 1472传输速度慢分片或CPU瓶颈检查MSS clamping和CPU使用率隧道时断时续中间网络抖动持续ping测丢包率5.5 几个容易忽略的细节第一个细节GRE隧道两端如果都是Linux默认的ttl是继承的建议显式设置ttl 255避免中间网络因为TTL耗尽丢包。第二个细节如果隧道上跑OSPF需要把网络类型设为point-to-point否则OSPF会尝试选举DR/BDR在点对点链路上没必要。第三个细节删除隧道时先删路由再删接口否则路由表里会残留无效条目。ip route del 172.16.2.0/24 dev gre1 ip tunnel del gre1第四个细节如果服务器重启后隧道没自动起来需要把配置写到启动脚本或网络配置文件里。不同发行版的写法不一样Ubuntu用netplanCentOS用ifcfg具体查对应文档。6. 一些个人体会GRE隧道这个技术说新不新说旧不旧。它没有花哨的功能但胜在简单、通用、够用。我这些年用下来最大的感受是越是简单的技术越要把基础打牢。GRE的坑基本都集中在路由、MTU、防火墙这三块把这三块吃透90%的问题都能自己解决。另外不要因为GRE不加密就完全排斥它。在可信网络内部GRE的效率比IPsec高配置也简单得多。如果确实需要加密GRE over IPsec是成熟方案虽然配置复杂一点但逻辑清晰排查起来也有章可循。最后分享一个小技巧建隧道之前先用tcpdump在两端物理接口上抓包确认协议47的包能正常收发。这一步花不了几分钟但能省掉后面很多来回折腾的时间。