1、基本参数
OpenWrt 版本:22.03.4(GL-XE300 路由器)
客户 GRE IP/专线接口 IP:120.236.136.227/29、专线网关:120.236.136.225,对等 IP:10.250.0.1/30
5G UPF 核心网侧 IP:183.235.54.118,对等 IP:10.250.0.2/30
终端地址池(物联网卡)静态 IP:10.60.0.0/19
该固件 缺少 /lib/netifd/proto/gre.sh 协议脚本,netifd 无法处理 proto 'gre',因此无法通过 /etc/config/network 持久化 GRE 隧道和路由。
通过 uci set network.route_gre1=route 的方式添加路由无效。
解决方案:采用 纯 Shell 脚本 + rc.local 管理隧道创建和路由,防火墙用 UCI 管理。
2、配置静态 IP、放行 ICMP
登录路由器管理面板,找到【互联网】>【以太网】配置项,填写专线提供的网络参数。
放行 ICMP(未持久化):
# 防火墙放行 ICMP
nft insert rule inet fw4 input_wan meta l4proto icmp accept
# 查看 input_wan 链
nft list chain inet fw4 input_wan | grep icmp
# 使用手机 Termux ping(外部网络)
ping -c 3 -W 2 120.236.136.227放行 ICMP(持久化):
# ping 放行
uci set firewall.allow_ping=rule
uci set firewall.allow_ping.name='Allow-Ping-WAN'
uci set firewall.allow_ping.proto='icmp'
uci set firewall.allow_ping.src='wan'
uci set firewall.allow_ping.target='ACCEPT'
uci commit firewall
/etc/init.d/firewall restart
# 验证(有输出证明OK)
uci show firewall.allow_ping
uci show firewall | grep -A5 "allow_ping"
# 删除(扩展、后需 commit、restart)
uci delete firewall.allow_ping手机/电脑连接路由器 wifi,百度搜索 ip。如果显示的是专线 ip,也能说明配置没问题。
3、启动 IP 转发
OpenWrt 默认已启用 IP 转发,确认一下:
cat /proc/sys/net/ipv4/ip_forward
# 应返回 1,若不是则执行:
echo 1 > /proc/sys/net/ipv4/ip_forward
uci set network.globals.ip_forward=1
uci commit network4、GRE、路由、防火墙(非持久)
(1)加载 GRE 模块
# 确认 GRE 模块是否已加载
lsmod | grep gre
# 已加载的输出:gre 2552 1 ip_gre
# 如果没有输出,执行加载
modprobe ip_gre
# 提示没有设备,则安装模块
opkg update
opkg list | grep -i gre # 查看有没有 GRE 的包
opkg install kmod-gre(2)创建 GRE 隧道
# 1、主隧道
ip tunnel add gre-pgw1 mode gre remote 183.235.54.118 local 120.236.136.227 ttl 255
ip addr add 10.250.0.2/30 dev gre-pgw1
ip link set gre-pgw1 up mtu 1400(3)添加路由
# 主路由(metric 100)
ip route add 10.60.0.0/19 via 10.250.0.1 dev gre-pgw1 metric 100
# 备用路由(metric 200)
# ip route add 10.6.0.0/22 via 172.16.0.1 dev gre-pgw2 metric 200(4)防火墙放行
OpenWrt 使用 firewall4(基于 nftables),而非 iptables:
# 放行 GRE 协议(在输入链)
nft add rule inet fw4 input meta l4proto gre accept
# 查看规则
nft list ruleset | grep -A5 -B5 gre5、GRE、路由、防火墙(持久)
(0)GRE 配置持久化(废弃)
该配置无效。
因精简版固件缺少 /lib/netifd/proto/gre.sh 协议脚本,
netifd 无法处理 proto 'gre' 配置,
故采用脚本绕过 netifd,直接使用 iproute2 命令管理 GRE 隧道。
vi /etc/config/network
# 在文件末尾添加:
config interface 'gre_pgw1'
option proto 'tunnel'
option tunnel 'gre'
option remote '183.235.54.118'
option local '120.236.136.227'
option mtu '1400'
option ipaddr '10.250.0.2'
option peeraddr '10.250.0.1'
option metric '100'
# 保存后,重启网络测试:
/etc/init.d/network restart
# 或者单独重启 GRE 接口(不重启整个网络)
ifdown gre_pgw1 && sleep 2 && ifup gre_pgw1(1)GRE Shell 模板脚本
GRE 隧道、路由创建脚本:
i)通过 vi 创建:
编辑: vi /root/gre-template
到开头 + 从当前行删除到末尾:gg dG
ii)通过 cat << EOF 创建:
脚本变量双引号的作用:
无引号:变量值会被 Shell 按空格、Tab、换行拆分成多个词,且 *、? 等通配符会被展开为匹配的文件名
有引号:变量值作为整体传递,保留空格和特殊字符,防止意外拆分和解释
PS:脚本不要用 Tab 缩进,用空格。Tab 会被解析为指令补全,导致命令异常中断。
cat > /root/gre-template << 'EOF'
#!/bin/sh
NAME="gre-xxx" # 隧道名称(唯一)
LOCAL_IP="120.236.136.227" # 本端物理 IP(所有隧道共用)
REMOTE_IP="183.235.54.118" # 对端物理 IP
TUNNEL_IP="10.250.0.2/30" # 本端隧道 IP
PEER_IP="10.250.0.1" # 对端隧道 IP
ROUTE_NET="10.60.0.0/19" # 目标网段
METRIC="100" # 路由优先级
case "$1" in
start)
logger -t "$NAME" "Starting GRE tunnel..."
# Wait for local IP to be ready (max 60 seconds)
retry=0
while ! ip addr show | grep -q "$LOCAL_IP" && [ $retry -lt 60 ]; do
sleep 1
retry=$((retry + 1))
done
if ! ip addr show | grep -q "$LOCAL_IP"; then
logger -t "$NAME" "ERROR: Local IP $LOCAL_IP not found, aborting"
exit 1
fi
logger -t "$NAME" "Local IP $LOCAL_IP found, creating tunnel..."
# Load GRE kernel module
modprobe ip_gre 2>/dev/null
# Remove existing tunnel if present
ip tunnel del "$NAME" 2>/dev/null
# Create GRE tunnel
ip tunnel add "$NAME" mode gre remote $REMOTE_IP local $LOCAL_IP ttl 255
# Assign tunnel IP
ip addr add "$TUNNEL_IP" dev "$NAME"
# Bring tunnel up
ip link set "$NAME" up mtu 1400
# Add or replace route (Does not impact other metric routes)
ip route replace "$ROUTE_NET" via $PEER_IP dev "$NAME" metric "$METRIC" table main 2>/dev/null
if ip link show "$NAME" > /dev/null 2>&1; then
logger -t "$NAME" "GRE tunnel started"
else
logger -t "$NAME" "GRE tunnel failed"
exit 1
fi
;;
stop)
ip route del "$ROUTE_NET" 2>/dev/null
ip link set "$NAME" down 2>/dev/null
ip tunnel del "$NAME" 2>/dev/null
logger -t "$NAME" "GRE tunnel removed"
;;
status)
if ip link show "$NAME" > /dev/null 2>&1; then
echo "✅ $NAME is UP"
echo ""
ip link show "$NAME" | grep -E "mtu|state"
echo ""
ip addr show "$NAME" | grep inet
echo ""
if ip route show | grep -q "$ROUTE_NET"; then
ip route show | grep "$ROUTE_NET"
else
echo "⚠️ Route $ROUTE_NET not found"
fi
else
echo "❌ $NAME is DOWN or does not exist"
fi
;;
*)
echo "Usage: $0 {start|stop|status}"
exit 1
;;
esac
EOF(2)通过 GRE Shell 模板脚本创建隧道脚本
# 4G 主隧道
cp /root/gre-template /etc/init.d/gre-4g-main
sed -i 's/NAME="gre-xxx"/NAME="gre-4g-main"/' /etc/init.d/gre-4g-main
sed -i 's/REMOTE_IP=".*"/REMOTE_IP="183.235.54.116"/' /etc/init.d/gre-4g-main
sed -i 's/TUNNEL_IP=".*"/TUNNEL_IP="10.250.0.10\/30"/' /etc/init.d/gre-4g-main
sed -i 's/PEER_IP=".*"/PEER_IP="10.250.0.9"/' /etc/init.d/gre-4g-main
sed -i 's/ROUTE_NET=".*"/ROUTE_NET="10.60.32.0\/19"/' /etc/init.d/gre-4g-main
sed -i 's/METRIC=".*"/METRIC="100"/' /etc/init.d/gre-4g-main
# 4G 备用隧道
cp /root/gre-template /etc/init.d/gre-4g-backup
sed -i 's/NAME="gre-xxx"/NAME="gre-4g-backup"/' /etc/init.d/gre-4g-backup
sed -i 's/REMOTE_IP=".*"/REMOTE_IP="183.235.54.118"/' /etc/init.d/gre-4g-backup
sed -i 's/TUNNEL_IP=".*"/TUNNEL_IP="10.250.0.2\/30"/' /etc/init.d/gre-4g-backup
sed -i 's/PEER_IP=".*"/PEER_IP="10.250.0.1"/' /etc/init.d/gre-4g-backup
sed -i 's/ROUTE_NET=".*"/ROUTE_NET="10.60.0.0\/19"/' /etc/init.d/gre-4g-backup
sed -i 's/METRIC=".*"/METRIC="200"/' /etc/init.d/gre-4g-backup
# 5G 主隧道
cp /root/gre-template /etc/init.d/gre-5g-main
sed -i 's/NAME="gre-xxx"/NAME="gre-5g-main"/' /etc/init.d/gre-5g-main
sed -i 's/REMOTE_IP=".*"/REMOTE_IP="183.235.54.68"/' /etc/init.d/gre-5g-main
sed -i 's/TUNNEL_IP=".*"/TUNNEL_IP="10.2.1.10\/30"/' /etc/init.d/gre-5g-main
sed -i 's/PEER_IP=".*"/PEER_IP="10.2.1.9"/' /etc/init.d/gre-5g-main
sed -i 's/ROUTE_NET=".*"/ROUTE_NET="172.16.2.0\/24"/' /etc/init.d/gre-5g-main
sed -i 's/METRIC=".*"/METRIC="100"/' /etc/init.d/gre-5g-main
# 5G 备用隧道
cp /root/gre-template /etc/init.d/gre-5g-backup
sed -i 's/NAME="gre-xxx"/NAME="gre-5g-backup"/' /etc/init.d/gre-5g-backup
sed -i 's/REMOTE_IP=".*"/REMOTE_IP="183.235.54.72"/' /etc/init.d/gre-5g-backup
sed -i 's/TUNNEL_IP=".*"/TUNNEL_IP="10.4.1.10\/30"/' /etc/init.d/gre-5g-backup
sed -i 's/PEER_IP=".*"/PEER_IP="10.4.1.9"/' /etc/init.d/gre-5g-backup
sed -i 's/ROUTE_NET=".*"/ROUTE_NET="172.16.2.0\/24"/' /etc/init.d/gre-5g-backup
sed -i 's/METRIC=".*"/METRIC="200"/' /etc/init.d/gre-5g-backup(3)设置权限
chmod +x /etc/init.d/gre-*(4)开机自启(rc.local)
# 一、只有一条隧道:通过指令在 /etc/rc.local 里添加:
if ! grep -q "gre-tunnel start" /etc/rc.local 2>/dev/null; then
sed -i '/exit 0/i # Start GRE tunnel\n/etc/init.d/gre-tunnel start &' /etc/rc.local
fi
# 立即启动(start 是幂等的,重复执行 = 先删后建)
/etc/init.d/gre-tunnel start
/etc/init.d/gre-tunnel status
# 二、多条隧道:vi /etc/rc.local,在 exit 0 前添加
# Start all GRE tunnels
/etc/init.d/gre-4g-main start &
/etc/init.d/gre-4g-backup start &
/etc/init.d/gre-5g-main start &
/etc/init.d/gre-5g-backup start &
# 启动/停止所有
ls /etc/init.d/gre-* | xargs -n1 -r sh -c '$0 start'
ls /etc/init.d/gre-* | xargs -n1 -r sh -c '$0 stop'
# 查看所有状态
ls /etc/init.d/gre-* | xargs -n1 -r sh -c '$0 status'(3)防火墙持久化
# 添加防火墙规则
uci add firewall rule
uci set firewall.@rule[-1].name='Allow-GRE'
uci set firewall.@rule[-1].proto='gre'
uci set firewall.@rule[-1].src='wan'
uci set firewall.@rule[-1].target='ACCEPT'
uci commit firewall
/etc/init.d/firewall restart
# 验证(有输出证明OK)
uci show firewall | grep -A5 "Allow-GRE"
# 删除(扩展、13 是 show 看到的序号 rule[13]、后需 commit、restart)
uci delete firewall.@rule[13] 2>/dev/null
6、连通验证
(1)通过命令检测
# 0、查看防火墙规则(有字眼 Allow-GRE)
# 配好后查一两次就行,日常不用看
nft list ruleset | grep -A5 -B5 "gre"
# 1、查看隧道状态
ip addr show gre-pgw1
ip link show gre-pgw1
ip link show
# 2、查看路由是否添加成功
ip route show | grep 10.60
ip route show
# 3. 查看日志(可选,shell 脚本我们自己 logger 打的日志)
# 启动成功:GRE tunnel started
# 这个是轮转/内存日志,一开始有,后续就查询为空了(正常现象)
logread | grep gre-tunnel | tail -20
# 测试隧道对端 IP
ping -c 3 10.250.0.1
# 测试目标网络(卡终端需开机)
ping -c 3 10.60.0.1
# 持久化测试:重启,重复上述指令
reboot
(2)通过脚本检测
保存:vi /root/check_gre.sh
赋予执行权限:chmod +x /root/check_gre.sh
#!/bin/sh
LOCAL_IP="120.236.136.227"
echo "===== GRE Tunnel Health Check ====="
echo ""
# 1. 检查本地IP是否存在
echo "[1] Local IP Check"
if ip addr show | grep -q "$LOCAL_IP"; then
echo " ✅ $LOCAL_IP found"
else
echo " ❌ $LOCAL_IP not found, aborting"
exit 1
fi
echo ""
# 2. 路由检测函数
check_route() {
local net=$1
printf " %-20s " "$net"
if ip route show | grep -q "$net"; then
echo "✅ FOUND"
ip route show | grep "$net" | head -1
else
echo "❌ NOT FOUND"
fi
}
echo "[2] Static Routes Check"
check_route "10.60.0.0/19"
check_route "10.60.32.0/19"
check_route "172.16.2.0/24"
echo ""
# 3. GRE隧道连通性检测
echo "[3] GRE Tunnel Connectivity"
echo " (ping -c 3 -W 2)"
check_ping() {
local ip=$1
printf " %-16s " "$ip"
if ping -c 3 -W 2 "$ip" > /dev/null 2>&1; then
echo "✅ OK"
else
echo "❌ FAILED"
fi
}
# GRE远端IP(公网)
echo ""
echo " --- Remote Public IPs ---"
for ip in 183.235.54.118 183.235.54.116 183.235.54.68 183.235.54.72; do
check_ping "$ip"
done
# GRE隧道内网IP
echo ""
echo " --- Tunnel Internal IPs ---"
for ip in 10.250.0.1 10.250.0.9 10.2.1.9 10.4.1.9; do
check_ping "$ip"
done
echo ""
echo "===== Check Completed ====="二、扩展
1、Win11 放行 ICMP(PING)
操作步骤:
按下 Win + R 键,输入 wf.msc,然后按回车,打开“高级安全 Windows Defender 防火墙”。
在左侧导航栏中,单击 【入站规则】。
在右侧的操作面板中,单击 【按组筛选】,然后从下拉列表中选择 【核心网络诊断】。
在筛选出的规则列表中,找到 ICMPv4 的入站规则。此时你会看到两条名称相似但远程地址不同的规则:
一条的远程地址为 “任何”
另一条的远程地址为 “本地子网”
右键单击远程地址为 【任何】 的那条规则,然后选择 【启用规则】。
属性 > 高级,把专用、公用勾上,应用(默认的网络都是公用,不勾上也 ping 不通)。
可用手机 Termux ping(外部网络):ping -c 3 -W 2 120.1.1.227


2、Openwrt init 脚本参数介绍
GRE 配置原计划通过 init 脚本实现,但因精简版固件中 USE_PROCD=0(非守护进程模式)无法生效,故改用普通 Shell 脚本执行。
这里简要记录 init 脚本的相关配置与使用,权作学习笔记。
init 脚本开头格式:
#!/bin/sh /etc/rc.common
START=99
USE_PROCD=1参数说明:
/etc/init.d/gre-tunnel enable 执行后,系统会在 /etc/rc.d/ 下创建一个指向脚本的链接。如 /etc/rc.d/S99gre-tunnel -> ../init.d/gre-tunnel
S = Start(启动时执行)
99 = 启动顺序(数字越大,越晚执行)
系统启动时,会按顺序执行 /etc/rc.d/S* 脚本。S99 意味着它会在启动流程的最后阶段执行,确保网络等其他服务已经就绪。