4、GRE 隧道原理:GRE协议头部结构、封装与解封装过程、GRE over IP 与 GRE over IPv6

好,咱们今天聊聊 GRE 隧道。说实话,GRE 是我最早接触的隧道协议之一。那时候刚做网络,觉得这玩意儿挺神奇的——能把一个包塞进另一个包里。后来在数据中心里折腾 Open vSwitch,发现 GRE 虽然老,但依然很能打。

嗯,咱们先搞清楚 GRE 到底是个啥。

4.1 GRE 协议头部结构

GRE,全称 Generic Routing Encapsulation,通用路由封装。说白了,就是一种“包中包”的技术。它定义了一种标准格式,让你能把一种协议的数据包,封装到另一种协议的数据包里传输。

我习惯把 GRE 头部想象成一个“信封”。原始的数据包是信纸,GRE 头部就是信封上的地址栏。这个信封长什么样?咱们来看看标准格式:

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|C| |K|S| Reserved0       | Ver |  Protocol Type                |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|      Checksum (optional)      |       Reserved1               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|      Key (optional)                                           |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|      Sequence Number (optional)                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

这个结构里,有几个关键字段我得跟你聊聊:

  • C(Checksum 标志位):1 位。如果置 1,表示头部后面跟着校验和字段。我在项目中遇到过,有些老旧设备对校验和的处理有 bug,建议你如果不需要校验,就别开这个位。
  • K(Key 标志位):1 位。置 1 表示有 Key 字段。这个 Key 在 OVS 里特别有用,可以用来标识不同的隧道。
  • S(Sequence Number 标志位):1 位。置 1 表示有序列号字段。用于检测丢包和乱序。
  • Protocol Type:2 字节。这个最重要,它告诉你信封里装的是什么协议。比如 0x0800 表示 IPv4,0x86DD 表示 IPv6。
  • Key:4 字节(可选)。OVS 里常用它来做隧道标识,相当于给隧道打了个标签。

核心要点:GRE 头部最小是 4 字节(只有 Protocol Type),最大可以到 16 字节(带上所有可选字段)。实际使用中,我建议至少带上 Key 字段,方便做多租户隔离。

4.2 封装与解封装过程

封装和解封装,说白了就是“打包”和“拆包”。我当年第一次配 GRE 隧道时,抓包看了半天才搞明白这个过程。咱们一步步来:

封装过程(发送端)

  1. 接收原始数据包:比如一个内网 IP 为 10.0.0.1 的主机,要发一个包给 10.0.0.2。
  2. 添加 GRE 头部:在原始 IP 头部前面,插入一个 GRE 头部。Protocol Type 设为 0x0800(IPv4)。
  3. 添加外层 IP 头部:在 GRE 头部前面,再添加一个 IP 头部。源 IP 是隧道本端公网地址,目的 IP 是隧道对端公网地址。
  4. 发送:这个双层 IP 包就在公网上传输了。

你想想看,原始包的内层 IP 地址是私有的,外层 IP 地址是公有的。这就是 GRE 能穿透公网的原因。

解封装过程(接收端)

  1. 接收外层包:收到一个 IP 包,目的 IP 是本机隧道接口地址。
  2. 检查协议号:IP 头部的 Protocol 字段是 47(GRE 的协议号)。
  3. 剥离外层头部:去掉外层 IP 头部和 GRE 头部。
  4. 转发内层包:剩下的原始 IP 包,根据内层目的 IP 进行路由转发。

我的经验:我曾经在排查一个 GRE 隧道不通的问题时,发现是 MTU 搞的鬼。封装后包变大了,超过了链路 MTU,导致分片或丢包。建议你把隧道接口的 MTU 设置为 1476 字节(标准 1500 减去 20 字节 IP 头再减去 4 字节 GRE 头)。

4.3 GRE over IP 与 GRE over IPv6

这里有个容易混淆的点。GRE 本身不关心底层网络是 IPv4 还是 IPv6。它只负责封装。但外层传输网络不同,处理方式也不同。

GRE over IPv4

这是最经典的用法。外层 IP 头部是 IPv4,协议号是 47。我早期做 IDC 网络时,跨机房互联基本都用这个。配置简单,兼容性好。

举个例子,在 OVS 里创建一个 GRE over IPv4 隧道:

ovs-vsctl add-port br0 gre0 -- set interface gre0 type=gre \
  options:remote_ip=203.0.113.1 \
  options:local_ip=198.51.100.1 \
  options:key=100

这里 remote_ip 和 local_ip 都是 IPv4 地址。key=100 就是 GRE 头部的 Key 字段,用来标识这个隧道。

GRE over IPv6

随着 IPv6 的普及,GRE over IPv6 也越来越常见。外层 IP 头部是 IPv6,下一头部(Next Header)是 47。嗯,这里要注意,IPv6 里不叫协议号,叫 Next Header。

在 OVS 里配置 GRE over IPv6:

ovs-vsctl add-port br0 gre6 -- set interface gre6 type=gre \
  options:remote_ip=2001:db8::1 \
  options:local_ip=2001:db8::2 \
  options:key=200

你看,语法几乎一样,只是 IP 地址换成了 IPv6 格式。

特性 GRE over IPv4 GRE over IPv6
外层头部 IPv4 头部(20 字节) IPv6 头部(40 字节)
协议标识 Protocol = 47 Next Header = 47
地址空间 32 位 128 位
MTU 开销 额外 24 字节(IP+GRE) 额外 44 字节(IPv6+GRE)
适用场景 传统 IPv4 网络 IPv6 骨干网、双栈环境

避坑指南:我曾经在 GRE over IPv6 上踩过一个坑。IPv6 不允许中间路由器做分片,如果封装后的包超过链路 MTU,会直接丢包并返回 ICMPv6 Packet Too Big。所以配置 GRE over IPv6 时,一定要把隧道接口的 MTU 设得更小,比如 1420 字节(1500 - 40 - 4 - 36 预留)。

4.4 GRE 在 OVS 中的实际应用

说了这么多理论,咱们看看在 OVS 里怎么用。我习惯把 GRE 隧道用在跨主机的虚拟机通信场景。

假设有两台宿主机:

  • Host A:192.168.1.10,上面有 VM1(IP 10.0.0.1)
  • Host B:192.168.1.20,上面有 VM2(IP 10.0.0.2)

要让 VM1 和 VM2 通信,可以在两台宿主机上各建一个 GRE 隧道:

Host A 配置:

ovs-vsctl add-br br-int
ovs-vsctl add-port br-int gre1 -- set interface gre1 type=gre \
  options:remote_ip=192.168.1.20 \
  options:local_ip=192.168.1.10 \
  options:key=100

Host B 配置:

ovs-vsctl add-br br-int
ovs-vsctl add-port br-int gre1 -- set interface gre1 type=gre \
  options:remote_ip=192.168.1.10 \
  options:local_ip=192.168.1.20 \
  options:key=100

配置完成后,VM1 发往 VM2 的包,会经过 br-int 进入 gre1 隧道接口,被封装成 GRE 包,通过物理网卡发到 Host B。Host B 解封装后,再把原始包交给 VM2。

整个过程对虚拟机完全透明。它们根本不知道中间经过了 GRE 封装。这就是隧道技术的魅力。

总结一下:GRE 虽然老,但稳定可靠。它的头部结构简单,封装解封装过程清晰。在 OVS 里配置也方便。不过要注意 MTU 问题和 Key 字段的使用。下一章咱们聊聊 Geneve,那家伙比 GRE 更灵活,但复杂度也上去了。