摘要:GRE(Generic Routing Encapsulation)是一种通用的三层隧道封装协议,广泛应用于多协议承载、组播传输和动态路由场景。本文将从 GRE 协议架构、报文格式、Keepalive 机制等维度进行深度解析,并提供完整的 Linux 生产环境配置实践。
关键词:GRE、隧道封装、路由协议、多协议承载
一、GRE 概述
1.1 什么是 GRE?
GRE(Generic Routing Encapsulation,通用路由封装)是由 Cisco 开发、IETF 标准化的隧道协议。RFC 2784(2000 年 3 月)是当前的标准文档,取代了早期的 RFC 1701(1994 年 10 月,已废弃)。RFC 2890(2000 年 9 月)增加了 Key 和序列号字段扩展。GRE 的核心思想是在一种网络层协议(如 IPv4)中封装另一种网络层协议(如 IPv6、IPX、AppleTalk 等)。
核心特性:
- 📦 多协议承载:支持 IPv4、IPv6、IPX、AppleTalk、MPLS 等多种乘客协议
- 🔄 组播支持:原生支持组播流量传输(IPSec 不支持)
- 🛣️ 动态路由:可在隧道上运行 OSPF、EIGRP、BGP 等动态路由协议
- 🔐 无加密:GRE 本身不提供加密,常与 IPSec 结合使用(GRE over IPSec)
1.2 GRE vs IPSec vs L2TP
| 特性 | GRE | IPSec | L2TP/IPSec |
|---|---|---|---|
| OSI 层级 | 第 3 层 | 第 3 层 | 第 2 层 |
| 加密能力 | ❌ 无 | ✅ 有 | ✅ 有 |
| 组播支持 | ✅ 支持 | ❌ 不支持 | ❌ 不支持 |
| 动态路由 | ✅ 支持 | ⚠️ 有限支持 | ❌ 不支持 |
| 多协议承载 | ✅ 支持 | ❌ 仅 IP | ✅ 支持(PPP) |
| 典型应用 | 站点互联、组播传输 | 安全 VPN | 远程接入 |
1.3 应用场景
| 场景类型 | 典型应用 | GRE 优势 |
|---|---|---|
| 多协议网络 | IPv6 over IPv4 隧道 | 原生支持多种乘客协议 |
| 组播传输 | 视频会议、IPTV 跨网传输 | 唯一支持组播的隧道协议 |
| 动态路由 | OSPF/BGP over Tunnel | 隧道接口支持路由协议邻居建立 |
| 数据中心互联 | DCI(Data Center Interconnect) | 低开销、高性能 |
| 混合云组网 | 私有云 - 公有云互联 | 简单配置、广泛支持 |
⚠️ 注意:GRE 不提供加密和认证,敏感数据传输需配合 IPSec 使用(GRE over IPSec)。
二、GRE 协议架构
2.1 协议栈位置
2.2 GRE 报文格式(RFC 2784)
2.3 头部字段详解
| 字段 | 长度 | 含义 |
|---|---|---|
| C (Checksum Present) | 1 比特 | 1=包含校验和字段 |
| R (Routing Present) | 1 比特 | 1=包含路由字段(必须为 0) |
| K (Key Present) | 1 比特 | 1=包含 Key 字段 |
| S (Sequence Number Present) | 1 比特 | 1=包含序列号字段(RFC 2890) |
| s (Strict Source Route) | 1 比特 | 严格源路由(必须为 0) |
| Recur | 3 比特 | 递归控制(防止嵌套隧道环路) |
| Flags | 5 比特 | 保留字段(必须为 0) |
| Ver | 3 比特 | 版本号(必须为 0) |
| Protocol Type | 16 比特 | 乘客协议类型(如 0x0800=IPv4, 0x86DD=IPv6) |
2.4 可选字段说明
| 字段 | 长度 | 启用条件 | 用途 |
|---|---|---|---|
| Checksum | 4 字节 | C=1 | 头部和数据校验 |
| Offset | 4 字节 | C=1 | 数据偏移(极少使用) |
| Key | 4 字节 | K=1 | 标识隧道会话,防止 spoofing |
| Sequence Number | 4 字节 | S=1 | 防止重放攻击,检测丢包 |
| Routing | 可变 | R=1 | 源路由(RFC 2784 规定必须为 0) |
三、GRE 隧道建立机制
3.1 无状态隧道
GRE 是无状态协议,不需要显式的隧道建立过程:
特点:
- ✅ 配置简单,无需协商
- ✅ 快速收敛,无握手延迟
- ❌ 无连接状态检测,需依赖 Keepalive
3.2 Keepalive 机制
GRE 本身无 Keepalive,需依赖以下机制检测隧道状态:
方式 1:使用监控脚本(Linux 无原生 Keepalive)
# Linux iproute2 不支持 keepalive 参数(Cisco 语法)
# 使用监控脚本检测隧道状态
cat > /usr/local/bin/gre-monitor.sh <<'EOF'
#!/bin/bash
REMOTE_IP="10.0.0.2"
INTERFACE="gre0"
if ! ping -c 1 -W 2 "$REMOTE_IP" >/dev/null 2>&1; then
echo "$(date): Tunnel $INTERFACE is down, restarting..." >> /var/log/gre-monitor.log
ip link set "$INTERFACE" down
sleep 5
ip link set "$INTERFACE" up
fi
EOF
chmod +x /usr/local/bin/gre-monitor.sh
# 添加到 crontab(每分钟检测一次)
# 注意:crontab 最小单位是分钟,如需更频繁检测使用 systemd timer
* * * * * /usr/local/bin/gre-monitor.sh
# 或使用 systemd timer(推荐)
cat > /etc/systemd/system/gre-monitor.service <<EOF
[Unit]
Description=GRE Tunnel Monitor
After=network.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/gre-monitor.sh
[Install]
WantedBy=multi-user.target
EOF
cat > /etc/systemd/system/gre-monitor.timer <<EOF
[Unit]
Description=Run GRE Monitor every 30 seconds
[Timer]
OnBootSec=1min
OnUnitActiveSec=30s
Unit=gre-monitor.service
[Install]
WantedBy=timers.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable gre-monitor.timer
sudo systemctl start gre-monitor.timer
方式 2:使用 BFD(Bidirectional Forwarding Detection,推荐)
# 安装 FRR(BFD 功能已包含在主包中)
sudo apt-get install -y frr
# 配置 BFD 会话(毫秒级检测)
vtysh -c "configure terminal" \
-c "bfd" \
-c " peer 10.0.0.2" \
-c " no shutdown"
方式 3:依赖路由协议 Hello
# OSPF over GRE
# OSPF Hello 包可检测邻居状态
router ospf 1
network 10.0.0.0 0.0.0.3 area 0
ip ospf hello-interval 10
ip ospf dead-interval 40
3.3 递归路由问题
问题描述:当隧道目的地址通过隧道本身可达时,会导致路由递归,隧道反复 up/down。
四、GRE over IPSec 安全增强
4.1 为什么需要 GRE over IPSec?
| 需求 | GRE | IPSec | GRE over IPSec |
|---|---|---|---|
| 组播传输 | ✅ | ❌ | ✅ |
| 动态路由 | ✅ | ⚠️ | ✅ |
| 数据加密 | ❌ | ✅ | ✅ |
| 完整性保护 | ❌ | ✅ | ✅ |
| 身份认证 | ❌ | ✅ | ✅ |
4.2 封装顺序
GRE over IPSec 有两种封装模式:
Tunnel Mode(隧道模式) Transport Mode(传输模式)
4.3 配置要点
# 关键配置原则
# 1. IPSec 保护 GRE 流量(协议 47)
# 2. GRE 隧道端点 = IPSec 隧道端点
# 3. 感兴趣流匹配 GRE 协议,而非乘客协议
# 错误配置示例(❌)
# 感兴趣流:10.0.0.0/24 → 192.168.0.0/24(乘客协议网段)
# 正确配置示例(✅)
# 感兴趣流:协议 47,源 1.1.1.1 → 目的 2.2.2.2(GRE 隧道端点)
五、生产环境配置实践
5.1 典型拓扑
5.2 【Linux】GRE 隧道配置
环境信息
| 角色 | 公网 IP | 内网网段 | 隧道 IP | 主机名 |
|---|---|---|---|---|
| 站点 A | 1.1.1.1 | 192.168.1.0/24 | 10.0.0.1/30 | site-a |
| 站点 B | 2.2.2.2 | 192.168.2.0/24 | 10.0.0.2/30 | site-b |
【站点 A】配置步骤
步骤 1:创建 GRE 隧道接口
# 创建 GRE 隧道接口
sudo ip tunnel add gre0 mode gre remote 2.2.2.2 local 1.1.1.1 ttl 255
# 启用接口
sudo ip link set gre0 up
# 配置隧道 IP 地址
sudo ip addr add 10.0.0.1/30 dev gre0
# 设置 MTU(建议值:1500 - 24 = 1476)
sudo ip link set gre0 mtu 1476
# 启用 Keepalive(可选,使用监控脚本)
# 参考 3.2 节 Keepalive 配置
步骤 2:配置路由
# 添加静态路由(通过隧道访问对端内网)
sudo ip route add 192.168.2.0/24 dev gre0
# 或者添加默认路由(所有流量走隧道)
# sudo ip route add 0.0.0.0/0 dev gre0
# 确保隧道目的地址通过物理接口可达(防止递归路由)
sudo ip route add 2.2.2.2/32 dev eth0
步骤 3:配置防火墙
# 放行 GRE 协议(IP 协议 47)
sudo iptables -A INPUT -p gre -s 2.2.2.2 -j ACCEPT
sudo iptables -A OUTPUT -p gre -d 2.2.2.2 -j ACCEPT
# 如果使用 GRE over IPSec
sudo iptables -A INPUT -p udp --dport 500 -j ACCEPT
sudo iptables -A INPUT -p udp --dport 4500 -j ACCEPT
sudo iptables -A INPUT -p esp -j ACCEPT
# 启用 IP 转发
sudo sysctl -w net.ipv4.ip_forward=1
echo "net.ipv4.ip_forward=1" | sudo tee -a /etc/sysctl.conf
步骤 4:验证隧道状态
# 查看隧道接口
ip -d link show gre0
# 查看接口状态
ip addr show gre0
# 查看路由表
ip route show
# 测试连通性
ping -I gre0 10.0.0.2
ping -I gre0 192.168.2.1
# 抓包验证(在 eth0 上抓 GRE 包)
sudo tcpdump -i eth0 -n proto 47
【站点 B】配置步骤
# 创建 GRE 隧道接口
sudo ip tunnel add gre0 mode gre remote 1.1.1.1 local 2.2.2.2 ttl 255
sudo ip link set gre0 up
sudo ip addr add 10.0.0.2/30 dev gre0
sudo ip link set gre0 mtu 1476
# Keepalive 使用监控脚本,参考 3.2 节
# 配置路由
sudo ip route add 192.168.1.0/24 dev gre0
sudo ip route add 1.1.1.1/32 dev eth0
# 配置防火墙
sudo iptables -A INPUT -p 47 -s 1.1.1.1 -j ACCEPT
sudo iptables -A OUTPUT -p 47 -d 1.1.1.1 -j ACCEPT
# 启用 IP 转发
sudo sysctl -w net.ipv4.ip_forward=1
5.3 【持久化配置】(Ubuntu/Debian)
创建网络配置文件:
# /etc/network/interfaces.d/gre0
auto gre0
iface gre0 inet tunnel
mode gre
endpoint 2.2.2.2
local 1.1.1.1
ttl 255
address 10.0.0.1
netmask 255.255.255.252
mtu 1476
pointopoint 10.0.0.2
或使用 systemd-networkd:
# /etc/systemd/network/10-gre0.netdev
[NetDev]
Name=gre0
Kind=gre
MTUBytes=1476
[Tunnel]
Local=1.1.1.1
Remote=2.2.2.2
TTL=255
# /etc/systemd/network/10-gre0.network
[Match]
Name=gre0
[Network]
Address=10.0.0.1/30
Peer=10.0.0.2
5.4 【GRE over IPSec】完整配置
步骤 1:配置 GRE 隧道(同上)
# 站点 A
sudo ip tunnel add gre0 mode gre remote 2.2.2.2 local 1.1.1.1 ttl 255
sudo ip link set gre0 up
sudo ip addr add 10.0.0.1/30 dev gre0
步骤 2:配置 IPSec(strongSwan)
# /etc/ipsec.conf - 站点 A
config setup
charondebug="ike 2, knl 2, cfg 2"
uniqueids=never
conn gre-ipsec
type=transport
keyexchange=ikev2
authby=secret
# 隧道端点(与 GRE 端点一致)
left=1.1.1.1
right=2.2.2.2
# 保护 GRE 流量(协议 47)
leftprotoport=47
rightprotoport=47
# 加密算法
ike=aes256gcm16-prfsha256-ecp256!
esp=aes256gcm16-ecp256!
# 生命周期
ikelifetime=8h
lifetime=1h
# 自动启动
auto=start
# /etc/ipsec.secrets
1.1.1.1 2.2.2.2 : PSK "GREoverIPSec@StrongKey2025!"
步骤 3:启动 IPSec
# 重启 strongSwan
sudo ipsec restart
# 查看状态
sudo ipsec status
sudo ipsec statusall
# 验证 GRE 流量是否被加密
sudo tcpdump -i eth0 -n host 2.2.2.2
# 应该看到 ESP 包,而非明文 GRE 包
六、性能优化建议
6.1 MTU 优化
GRE 封装会增加额外开销:
- 外层 IP 头:20 字节
- GRE 头部:4 字节(基础),启用 Key/Sequence 后可达 12-16 字节
# 推荐 MTU 设置
# 物理接口 MTU 1500 - GRE 开销 24 = 1476
sudo ip link set gre0 mtu 1476
# 如果使用 GRE over IPSec
# 物理接口 MTU 1500 - IPSec(50-73) - GRE(24) ≈ 1400
sudo ip link set gre0 mtu 1400
MTU 问题诊断
# 测试 MTU(通过隧道接口发送,需扣除 IP+ICMP 头 28 字节)
# 纯 GRE 场景:MTU 1476 → ICMP payload = 1476 - 28 = 1448
ping -M do -s 1448 10.0.0.2
# GRE over IPSec 场景:MTU 1400 → ICMP payload = 1400 - 28 = 1372
ping -M do -s 1372 10.0.0.2
# 查看分片统计
netstat -s | grep -i fragment
6.2 多队列优化(多核 CPU)
# 启用多队列(需要内核支持)
sudo ip link set gre0 numtxqueues 4
sudo ip link set gre0 txqueuelen 1000
# 查看队列统计
ethtool -S gre0
6.3 路由优化
# 使用策略路由(多隧道场景)
ip rule add from 192.168.1.0/24 table 100
ip route add default via 10.0.0.2 dev gre0 table 100
# 启用 ECMP(等价多路径)
ip route add 192.168.2.0/24 \
nexthop via 10.0.0.2 dev gre0 weight 1 \
nexthop via 10.0.0.6 dev gre1 weight 1
6.4 Keepalive 调优
# 快速故障检测(毫秒级)
# Linux iproute2 不支持 keepalive 参数(Cisco 语法)
# 请使用 3.2 节的监控脚本或 BFD 方案
# 保守配置(低带宽链路)
# Linux iproute2 不支持 keepalive 参数(Cisco 语法)
# 请使用 3.2 节的监控脚本或 BFD 方案
七、故障排查
7.1 常见故障及解决方案
故障 1:隧道接口 up 但无法 ping 通
可能原因
- 路由未配置
- 防火墙阻止 GRE 协议
- 对端未配置
排查步骤
# 1. 检查接口状态
ip -d link show gre0
# 应显示:gre0: <POINTOPOINT,UP,LOWER_UP>
# 2. 检查路由
ip route show | grep gre0
# 3. 检查防火墙
sudo iptables -L -n -v | grep 47
# 4. 抓包验证
sudo tcpdump -i eth0 -n proto 47
故障 2:隧道反复 up/down
可能原因
- Keepalive 超时
- 路由递归
- 网络不稳定
解决方案
# 调整 Keepalive
# Linux iproute2 不支持 keepalive 参数(Cisco 语法)
# 请使用 3.2 节的监控脚本或 BFD 方案
# 检查路由递归
ip route get 2.2.2.2
# 应显示通过物理接口,而非 gre0
# 添加主机路由
sudo ip route add 2.2.2.2/32 dev eth0
故障 3:GRE over IPSec 不通
可能原因
- IPSec SA 未建立
- 感兴趣流配置错误
- NAT 设备阻止
排查步骤
# 1. 检查 IPSec 状态
sudo ipsec status
# 2. 检查感兴趣流
# 应匹配协议 47,而非乘客协议
grep -A 10 "conn gre-ipsec" /etc/ipsec.conf
# 3. 检查 NAT 穿越
sudo ipsec statusall | grep NAT
7.2 诊断命令汇总
# ==================== 接口状态 ====================
ip -d link show gre0 # 查看隧道详情
ip addr show gre0 # 查看 IP 地址
ethtool -S gre0 # 查看统计信息
# ==================== 路由检查 ====================
ip route show # 查看路由表
ip route get 192.168.2.1 # 检查特定路由
ip route show table all # 查看所有路由表
# ==================== 抓包分析 ====================
# 物理接口抓包(查看 GRE 包)
sudo tcpdump -i eth0 -n proto 47
# 隧道接口抓包(查看乘客协议包)
sudo tcpdump -i gre0 -n
# 详细抓包(解码 GRE)
sudo tcpdump -i eth0 -n -vv proto 47
# ==================== IPSec 检查 ====================
sudo ipsec status # 查看 SA 状态
sudo ipsec trafficstatus # 查看流量统计
sudo cat /var/log/charon.log # 查看日志
# ==================== 性能测试 ====================
# 带宽测试
iperf3 -c 10.0.0.2 -t 60
# 延迟测试
ping -c 100 10.0.0.2
# MTU 测试
ping -M do -s 1448 10.0.0.2 # 1448+28=1476(纯 GRE 场景)
八、高级应用场景
8.1 动态路由 over GRE(OSPF 示例)
# 站点 A - OSPF 配置(使用 FRR)
sudo apt-get install -y frr frr-pythontools
# /etc/frr/ospfd.conf
router ospf
router-id 1.1.1.1
network 10.0.0.0/30 area 0.0.0.0
network 192.168.1.0/24 area 0.0.0.0
passive-interface eth0
!
# 站点 B - OSPF 配置
# /etc/frr/ospfd.conf
router ospf
router-id 2.2.2.2
network 10.0.0.0/30 area 0.0.0.0
network 192.168.2.0/24 area 0.0.0.0
passive-interface eth0
!
# 重启 FRR 服务
sudo systemctl restart frr
# 验证 OSPF 邻居
vtysh -c "show ip ospf neighbor"
# 查看 OSPF 路由
vtysh -c "show ip route ospf"
8.2 组播传输 over GRE
# GRE 原生支持组播,无需特殊配置
# 1. 启用组播路由
sudo sysctl -w net.ipv4.conf.all.mc_forwarding=1
# 2. 配置 PIM-SM(协议无关组播)
# /etc/frr/pimd.conf
ip pim rp-address 192.168.1.1
interface gre0
ip pim sm
!
interface eth0
ip pim sm
!
# 3. 验证组播
show ip mroute
show ip pim neighbor
8.3 多隧道负载均衡
# 创建多个 GRE 隧道
sudo ip tunnel add gre0 mode gre remote 2.2.2.2 local 1.1.1.1
sudo ip tunnel add gre1 mode gre remote 2.2.2.3 local 1.1.1.2
# 配置 ECMP 路由
sudo ip route add 192.168.2.0/24 \
nexthop via 10.0.0.2 dev gre0 weight 1 \
nexthop via 10.0.0.6 dev gre1 weight 1
# 验证负载均衡
watch -n1 'ip -s link show gre0; ip -s link show gre1'
九、安全加固建议
9.1 基础安全措施
# 限制 GRE 源地址
sudo iptables -A INPUT -p gre -s 2.2.2.2 -j ACCEPT
sudo iptables -A INPUT -p gre -j DROP
# 启用反向路径过滤
sudo sysctl -w net.ipv4.conf.all.rp_filter=1
sudo sysctl -w net.ipv4.conf.default.rp_filter=1
# 限制 ICMP 重定向
sudo sysctl -w net.ipv4.conf.all.accept_redirects=0
9.2 GRE over IPSec 最佳实践
# /etc/ipsec.conf
conn gre-ipsec
# 使用 IKEv2
keyexchange=ikev2
# 强加密算法
ike=aes256gcm16-prfsha256-ecp256!
esp=aes256gcm16-ecp256!
# 启用 PFS
dpdaction=clear
rekey=yes
# 严格模式
leftfirewall=yes
installpolicy=yes
9.3 监控与告警
# 监控隧道状态
#!/bin/bash
# /usr/local/bin/gre-monitor.sh
INTERFACE="gre0"
# 注意:GRE 隧道接口的 ip link state 通常为 UNKNOWN,
# 应检查 flags 中的 UP 标志以及连通性
if ! ip link show "$INTERFACE" | grep -q '<.*UP.*>'; then
echo "ALERT: GRE tunnel $INTERFACE is DOWN" | \
mail -s "GRE Tunnel Alert" admin@example.com
elif ! ping -c 1 -W 2 10.0.0.2 >/dev/null 2>&1; then
echo "ALERT: GRE tunnel $INTERFACE has no connectivity" | \
mail -s "GRE Tunnel Alert" admin@example.com
fi
# 添加到 crontab
# */5 * * * * /usr/local/bin/gre-monitor.sh
十、常见问题 FAQ
Q1: GRE 和 IPIP 有什么区别?
| 特性 | GRE | IPIP |
|---|---|---|
| 协议号 | 47 | 4 |
| 多协议支持 | ✅ | ❌(仅 IPv4) |
| 组播支持 | ✅ | ❌ |
| 头部开销 | 24 字节 | 20 字节 |
| 推荐场景 | 多协议、组播 | 简单 IPv4 over IPv4 |
Q2: 为什么 GRE 支持组播而 IPSec 不支持?
原因:IPSec 的 SA 是点对点的,组播地址无法建立 SA。GRE 无状态,直接封装组播包即可传输。
解决方案:GRE over IPSec,由 GRE 承载组播,IPSec 提供加密。
Q3: GRE 隧道 MTU 如何计算?
Q4: 如何排查 GRE 隧道性能问题?
# 1. 检查丢包
ip -s link show gre0
# 2. 检查 CPU 使用率
top -p $(pgrep -f 'gre0')
# 3. 带宽测试
iperf3 -c 10.0.0.2 -t 60 -P 4
# 4. 检查中断分布
cat /proc/interrupts | grep gre0
Q5: GRE 还是 VXLAN/Geneve?
| 特性 | GRE | VXLAN | Geneve |
|---|---|---|---|
| 标准 | RFC 2784 | RFC 7348 | RFC 8926 |
| 开销 | 24 字节 | 50 字节 | 可变 |
| VNI 支持 | ❌ | ✅ (24 位) | ✅ (24 位) |
| 扩展性 | 低 | 中 | 高 |
| 推荐场景 | 传统 VPN | 数据中心 Overlay | 新一代 Overlay |
十一、总结
GRE 作为一种简单、高效的三层隧道协议,在多协议承载、组播传输和动态路由场景下仍具有不可替代的优势。
核心要点回顾:
- 无状态协议:配置简单,无需协商,快速收敛
- 多协议支持:IPv4、IPv6、IPX、MPLS 等
- 组播传输:唯一支持组播的隧道协议
- 动态路由:支持 OSPF、BGP 等路由协议
- 安全增强:配合 IPSec 实现加密(GRE over IPSec)
适用场景:
- ✅ 多协议网络互联
- ✅ 组播流量跨网传输
- ✅ 需要动态路由的站点互联
- ✅ 数据中心 Overlay 网络
- ⚠️ 敏感数据传输需配合 IPSec
随着 VXLAN、Geneve 等新一代 Overlay 协议的兴起,GRE 在数据中心场景的应用有所减少,但在传统企业网络和组播传输领域仍是首选方案。
参考文献
- RFC 2784 - Generic Routing Encapsulation (GRE)
- RFC 2890 - Key and Sequence Number Extensions to GRE
- RFC 1701 - Generic Routing Encapsulation
- Linux IP Tunneling HOWTO
- strongSwan Documentation