# 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) ### 安装 ```bash # 克隆仓库 git clone https://github.com/yanglc721/tunnelgen.git cd tunnelgen # 添加执行权限 chmod +x tunnel-generator.sh # 运行脚本 sudo ./tunnel-generator.sh ``` ### 快速安装 ```bash # 下载脚本 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) ```ini [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` 路由表注入路由。这可能导致: 1. 隧道端点的路由被覆盖 2. 到对端 IP 的流量被路由到隧道接口 3. 形成路由环路,导致隧道断联 ``` ┌─────────────────────────────────────────────┐ │ 问题: bird 注入路由后 main 表的状态 │ ├─────────────────────────────────────────────┤ │ 2001:db8:2000::1 via ... dev gre-hk1 │ ← 被覆盖! │ 导致隧道流量又被路由回隧道,形成死循环 │ └─────────────────────────────────────────────┘ ``` ### 解决方案 创建一个 bird 无法影响的**专用路由表**: ``` ┌─────────────────────────────────────────────┐ │ 流量到对端IP │ │ destination = 2001:db8:2000::1 │ └─────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────┐ │ PBR规则:priority 50 │ │ to → 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) 之前执行,确保隧道端点流量使用干净的路由表。 ## 服务管理 ```bash # 启动服务 systemctl start gre-hk1 # 停止服务 systemctl stop gre-hk1 # 查看状态 systemctl status gre-hk1 # 开机自启 systemctl enable gre-hk1 # 禁用开机自启 systemctl disable gre-hk1 ``` ## 验证隧道 ### 检查隧道接口 ```bash ip link show gre-hk1 ip -6 addr show gre-hk1 ``` ### 检查 PBR 规则 (IPv6) ```bash # 查看 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 ``` ### 测试连通性 ```bash # ping 对端隧道地址 ping6 2001:db8:2000::1 # 或通过隧道 ping 对端内网地址 ping6 <对端内网IPv6> ``` ## 删除隧道 ```bash # 停止并禁用服务 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,删除对应行 ``` ## 注意事项 1. **多网卡环境**: 请确保选择正确的物理网卡,IX 专用网卡通常无法提供互联网服务 2. **网关变更**: 如果物理网关变更,需要更新 PBR 脚本并重启服务 ```bash # 编辑 PBR 脚本 vi /usr/local/sbin/gre-hk1-pbr-setup.sh # 重启服务 systemctl restart gre-hk1 ``` 3. **防火墙**: 确保 GRE/VXLAN 协议通过防火墙 ```bash # 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 ``` 4. **MTU**: GRE 隧道会减少 MTU,可能需要调整 ```bash 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) ```bash sudo ./tunnel-generator.sh # 选择: IPv4 -> SSH TUN -> 服务端 # 选择隧道 IP 类型: IPv6 # 输入 SSH 端口、用户 # 隧道 IP 默认: fd00::1 (服务端) / fd00::2 (客户端) ``` 服务端会自动: 1. 启用 SSH PermitTunnel 2. 重启 SSH 服务 3. 生成 IP 配置脚本 #### 客户端(NAT 内) ```bash sudo ./tunnel-generator.sh # 选择: IPv4 -> SSH TUN -> 客户端 # 输入服务端 IP: 23.154.9.54 # 选择隧道 IP 类型: IPv6 # 隧道 IP 默认: fd00::2 (本地) / fd00::1 (对端) ``` 客户端会自动: 1. 检查/生成 SSH 密钥 2. 显示公钥(需要添加到服务端) 3. 创建 systemd 服务(自动连接和重连) #### 添加 SSH 公钥 在服务端添加客户端的公钥: ```bash # 在服务端执行 echo 'ssh-ed25519 AAAA... client@hostname' >> /root/.ssh/authorized_keys ``` #### 验证连接(IPv6 隧道 IP) ```bash # 客户端 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 是否生效: ```bash ip -6 route get <远端IP> ``` 应显示走物理接口,而不是隧道接口。 ### Q: bird 重启后隧道断开? 确保 PBR 规则优先级正确 (50-51),在 main 表之前查询。 ### Q: 如何查看当前所有隧道? ```bash # GRE 隧道 ip tunnel show # 所有虚拟接口 ip link show type gre ip link show type vxlan ``` ## 许可证 MIT License ## 贡献 欢迎提交 Issue 和 Pull Request! ## 作者 [yanglc721](https://github.com/yanglc721) ## 链接 - [GitHub 仓库](https://github.com/yanglc721/tunnelgen) - [问题反馈](https://github.com/yanglc721/tunnelgen/issues)