|
|
||
|---|---|---|
| README.md | ||
| tunnel-generator.sh | ||
README.md
TunnelGen
GRE/VXLAN 隧道服务生成器 - 自动生成 systemd 服务文件,支持 IPv4/IPv6,IPv6 支持 PBR 防止 bird 路由冲突。
功能特性
- 双协议支持: IPv4 和 IPv6
- 三种隧道类型: GRE、VXLAN、SSH TUN
- 智能检测: 自动检测网络接口和网关
- IPv6 PBR: 创建专用路由表,防止 bird 路由覆盖导致隧道断联
- SSH TUN: TCP 隧道方案,适用于 UDP 受限环境
- systemd 集成: 生成开机自启的服务文件
- 交互式界面: 简单易用的中文交互界面
快速开始
环境要求
- Linux 系统
- root 权限
ip命令 (iproute2)
安装
# 克隆仓库
git clone https://github.com/yanglc721/tunnelgen.git
cd tunnelgen
# 添加执行权限
chmod +x tunnel-generator.sh
# 运行脚本
sudo ./tunnel-generator.sh
快速安装
# 下载脚本
curl -fsSL https://raw.githubusercontent.com/yanglc721/tunnelgen/main/tunnel-generator.sh -o tunnel-generator.sh
# 添加执行权限
chmod +x tunnel-generator.sh
# 运行脚本
sudo ./tunnel-generator.sh
使用说明
交互式配置
运行脚本后,按照提示进行配置:
========================================
GRE/VXLAN 隧道服务生成器
========================================
选择 IP 版本:
1) IPv4
2) IPv6
请输入选项 [1-2]: 2
[信息] 已选择: ipv6
选择隧道类型:
1) GRE
2) VXLAN
请输入选项 [1-2]: 1
[信息] 已选择: gre
请输入隧道名称 (例如: gre-hk1, vxlan-hk4): gre-hk1
请输入本地 IPv6 地址: 2001:db8:1000::1
请输入远端 IPv6 地址: 2001:db8:2000::1
可用的网络接口:
=====================================
[1] eth0 状态:UP IPv6: 2001:db8:1000::1
[2] ix-ams 状态:UP IPv6: 2001:db8:9000::1
=====================================
[信息] 自动检测到网关: fe80::1
========================================
配置摘要:
========================================
隧道名称: gre-hk1
IP 版本: ipv6
隧道类型: gre
本地 IP: 2001:db8:1000::1
远端 IP: 2001:db8:2000::1
接口: eth0
网关: fe80::1
PBR: 已启用 (使用专用路由表)
========================================
生成服务文件? [Y/n]: y
立即启用并启动服务? [Y/n]: y
配置参数说明
| 参数 | 说明 | 示例 |
|---|---|---|
| IP 版本 | 选择 IPv4 或 IPv6 | ipv6 |
| 隧道类型 | GRE / VXLAN / SSH TUN | gre |
| 隧道名称 | 服务标识符,用于生成服务文件名 | gre-hk1 |
| 本地 IP | 本地隧道端点地址 | 2001:db8:1000::1 |
| 远端 IP | 对端隧道端点地址 | 2001:db8:2000::1 |
| 接口 | 物理网络接口 (承载隧道流量) | eth0 |
| 网关 | PBR 使用的网关 (仅 IPv6) | fe80::1 |
| VNI | VXLAN 网络标识符 (仅 VXLAN) | 100 |
| 目标端口 | VXLAN 端口 (仅 VXLAN) | 4789 |
SSH TUN 特有参数
| 参数 | 说明 | 示例 |
|---|---|---|
| 角色 | 服务端 (公网 IP) 或客户端 (NAT 内) | server / client |
| SSH 端口 | SSH 服务端口 | 22 |
| SSH 用户 | SSH 登录用户 | root |
| 隧道 IP 类型 | 隧道内部 IP 版本 | ipv4 / ipv6 |
| 本地隧道 IP | 隧道内的本地 IP | fd00::1 |
| 对端隧道 IP | 隧道内的对端 IP | fd00::2 |
生成的文件
运行脚本后会生成以下文件:
| 文件路径 | 说明 |
|---|---|
/etc/systemd/system/<隧道名>.service |
systemd 服务文件 |
/usr/local/sbin/<隧道名>-pbr-setup.sh |
PBR 设置脚本 (仅 IPv6 GRE/VXLAN) |
/usr/local/sbin/<隧道名>-ip-config.sh |
IP 配置脚本 (仅 SSH TUN 服务端) |
/etc/iproute2/rt_tables |
路由表定义 (追加,仅 IPv6 GRE/VXLAN) |
服务文件示例 (IPv6 GRE)
[Unit]
Description=GRE 隧道 gre-hk1
After=network.target network-online.target
Wants=network-online.target
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStartPre=/usr/local/sbin/gre-hk1-pbr-setup.sh
ExecStart=/bin/sh -c "ip tunnel add gre-hk1 mode ip6gre remote 2001:db8:2000::1 local 2001:db8:1000::1 ttl 255 && ip link set gre-hk1 up"
ExecStop=/bin/sh -c "ip link set gre-hk1 down; ip tunnel del gre-hk1; ip -6 rule del to 2001:db8:2000::1 table gre-hk1_underlay priority 50 || true; ip -6 rule del from 2001:db8:1000::1 table gre-hk1_underlay priority 51 || true"
[Install]
WantedBy=multi-user.target
IPv6 PBR 原理
问题背景
当运行 bird 等 BGP 路由软件时,bird 会向 main 路由表注入路由。这可能导致:
- 隧道端点的路由被覆盖
- 到对端 IP 的流量被路由到隧道接口
- 形成路由环路,导致隧道断联
┌─────────────────────────────────────────────┐
│ 问题: bird 注入路由后 main 表的状态 │
├─────────────────────────────────────────────┤
│ 2001:db8:2000::1 via ... dev gre-hk1 │ ← 被覆盖!
│ 导致隧道流量又被路由回隧道,形成死循环 │
└─────────────────────────────────────────────┘
解决方案
创建一个 bird 无法影响的专用路由表:
┌─────────────────────────────────────────────┐
│ 流量到对端IP │
│ destination = 2001:db8:2000::1 │
└─────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────┐
│ PBR规则:priority 50 │
│ to <remote> → table gre-hk1_underlay │
└─────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────┐
│ gre-hk1_underlay 表(干净,不受bird影响) │
│ │
│ 2001:db8:2000::1 via fe80::1 dev eth0 │
│ ↑ 正确!走物理网卡 │
└─────────────────────────────────────────────┘
PBR 规则优先级
优先级 50: to <远端IP> table <隧道名>_underlay
优先级 51: from <本地IP> table <隧道名>_underlay
...
优先级 32766: from all lookup main (默认规则)
PBR 规则优先级 50-51,在默认 main 表查询 (32766) 之前执行,确保隧道端点流量使用干净的路由表。
服务管理
# 启动服务
systemctl start gre-hk1
# 停止服务
systemctl stop gre-hk1
# 查看状态
systemctl status gre-hk1
# 开机自启
systemctl enable gre-hk1
# 禁用开机自启
systemctl disable gre-hk1
验证隧道
检查隧道接口
ip link show gre-hk1
ip -6 addr show gre-hk1
检查 PBR 规则 (IPv6)
# 查看 PBR 规则
ip -6 rule show | grep priority
# 查看专用路由表
ip -6 route show table gre-hk1_underlay
# 验证路由是否正确
ip -6 route get 2001:db8:2000::1
# 应显示: dev eth0 (物理接口),而不是 dev gre-hk1
测试连通性
# ping 对端隧道地址
ping6 2001:db8:2000::1
# 或通过隧道 ping 对端内网地址
ping6 <对端内网IPv6>
删除隧道
# 停止并禁用服务
systemctl stop gre-hk1
systemctl disable gre-hk1
# 删除服务文件
rm /etc/systemd/system/gre-hk1.service
rm /usr/local/sbin/gre-hk1-pbr-setup.sh # 如果存在
# 重载 systemd
systemctl daemon-reload
# (可选) 删除路由表定义
# 编辑 /etc/iproute2/rt_tables,删除对应行
注意事项
-
多网卡环境: 请确保选择正确的物理网卡,IX 专用网卡通常无法提供互联网服务
-
网关变更: 如果物理网关变更,需要更新 PBR 脚本并重启服务
# 编辑 PBR 脚本 vi /usr/local/sbin/gre-hk1-pbr-setup.sh # 重启服务 systemctl restart gre-hk1 -
防火墙: 确保 GRE/VXLAN 协议通过防火墙
# GRE ip6tables -A INPUT -p ipv6-encap -j ACCEPT ip6tables -A OUTPUT -p ipv6-encap -j ACCEPT # VXLAN (UDP 端口) ip6tables -A INPUT -p udp --dport 4789 -j ACCEPT ip6tables -A OUTPUT -p udp --dport 4789 -j ACCEPT -
MTU: GRE 隧道会减少 MTU,可能需要调整
ip link set gre-hk1 mtu 1400
与 bird 配合
在 bird 配置中,确保 kernel 协议正确配置:
protocol kernel {
scan time 60;
import all;
export all;
kernel table 254; # main 表
}
# 隧道接口路由由 PBR 处理,无需在 bird 中特殊配置
支持的隧道类型
| 类型 | IPv4 模式 | IPv6 模式 | 特点 |
|---|---|---|---|
| GRE | gre |
ip6gre |
标准 IP 隧道,开销小,性能最佳 |
| VXLAN | vxlan |
vxlan |
支持 VNI,适合数据中心 |
| SSH TUN | TCP | TCP | 基于 SSH,适用于 UDP 受限环境 |
SSH TUN 隧道
SSH TUN 是基于 SSH 协议的 TCP 隧道,适用于 UDP 端口被阻挡的环境。
使用场景
- UDP 端口被运营商或防火墙阻挡
- 一端在 NAT 内,只有有限的公网端口
- 需要加密传输的场景
隧道 IP 类型
SSH TUN 支持两种隧道内部 IP:
| 类型 | 默认地址范围 | 说明 |
|---|---|---|
| IPv4 | 10.0.0.1/24 | 适合 IPv4 内网通信 |
| IPv6 | fd00::1/64 | 适合 IPv6 内网通信(推荐) |
配置步骤
服务端(有公网 IP)
sudo ./tunnel-generator.sh
# 选择: IPv4 -> SSH TUN -> 服务端
# 选择隧道 IP 类型: IPv6
# 输入 SSH 端口、用户
# 隧道 IP 默认: fd00::1 (服务端) / fd00::2 (客户端)
服务端会自动:
- 启用 SSH PermitTunnel
- 重启 SSH 服务
- 生成 IP 配置脚本
客户端(NAT 内)
sudo ./tunnel-generator.sh
# 选择: IPv4 -> SSH TUN -> 客户端
# 输入服务端 IP: 23.154.9.54
# 选择隧道 IP 类型: IPv6
# 隧道 IP 默认: fd00::2 (本地) / fd00::1 (对端)
客户端会自动:
- 检查/生成 SSH 密钥
- 显示公钥(需要添加到服务端)
- 创建 systemd 服务(自动连接和重连)
添加 SSH 公钥
在服务端添加客户端的公钥:
# 在服务端执行
echo 'ssh-ed25519 AAAA... client@hostname' >> /root/.ssh/authorized_keys
验证连接(IPv6 隧道 IP)
# 客户端
ping6 fd00::1 # 服务端隧道 IP
# 服务端(连接建立后先运行 IP 配置脚本)
/usr/local/sbin/<隧道名>-ip-config.sh
ping6 fd00::2 # 客户端隧道 IP
性能说明
| 隧道类型 | 典型速度 | CPU 占用 |
|---|---|---|
| GRE/VXLAN | 线速 (1Gbps+) | 低 |
| SSH TUN | 100-500 Mbps | 中等 |
SSH TUN 由于 SSH 加密开销,性能低于 GRE/VXLAN,但足以满足大多数应用场景。
常见问题
Q: IPv6 隧道启动后无法连通?
检查 PBR 是否生效:
ip -6 route get <远端IP>
应显示走物理接口,而不是隧道接口。
Q: bird 重启后隧道断开?
确保 PBR 规则优先级正确 (50-51),在 main 表之前查询。
Q: 如何查看当前所有隧道?
# GRE 隧道
ip tunnel show
# 所有虚拟接口
ip link show type gre
ip link show type vxlan
许可证
MIT License
贡献
欢迎提交 Issue 和 Pull Request!