Files
flvx/plans/069-udp-tunnel-fix.md
sagitchu 630e012ec1 fix(tunnel): resolve UDP stream interruption and add KCP protocol support
- Increase UDP listener default TTL from 5s to 30s to prevent idle disconnect
- Add mux keepalive config (15s interval, 45s timeout) to tunnel relay handler
- Add KCP as tunnel chain transport protocol with keepalive and UDP mode default
- Add KCP protocol option to tunnel UI (frontend)
- Remove generic 'tcp' fallback key from KCP metadata to prevent false TCP mode
- Simplify forward service config by removing unused tunnelTLSProtocol parameter
2026-04-20 23:57:43 +08:00

88 lines
4.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 069: UDP 隧道转发断流修复 + KCP 协议支持
## 问题分析
GOST 隧道转发 UDP 断流的根因涉及三个超时层:
### 1. UDP 虚拟连接 TTL 过短(5秒)— 主因
- `go-gost/x/listener/udp/metadata.go:11`: `defaultTTL = 5s`
- `go-gost/x/internal/net/udp/pool.go:79-115`: `idleCheck()` 每 TTL 周期标记空闲连接,下一周期关闭
- **影响**: UDP 流无数据包超过 ~10 秒即被静默关闭
- **后端配置**: `control_plane.go:1607-1613` 设置了 `keepAlive: true`,但仅在 `tunnelTLSProtocol=true` 时设 `ttl: "10s"`,常规隧道转发不设 TTL 覆盖
### 2. Smux Keepalive 未显式配置
- smux `DefaultConfig()`: `KeepAliveInterval=10s`, `KeepAliveTimeout=30s`
- 后端 `buildTunnelChainServiceConfig` 生成 relay handler 时不设置 mux 参数
- 依赖 smux 默认值,但中间 NAT/防火墙可能先于 30s 断开 TCP 连接
### 3. 隧道仅依赖 TCP 传输 — 无 UDP 备选
- 隧道链节点间仅支持 TLS/TCP 传输
- TCP 队头阻塞 + 单连接承载所有流 + 无 UDP 级别的容错
## 修复方案
### Part A: 修复现有问题(低风险,即时生效)
#### A1. 增大 UDP listener 默认 TTL
- **文件**: `go-gost/x/listener/udp/metadata.go`
- **改动**: `defaultTTL = 30s`(从 5s)
- **原因**: 5s 对实际场景太激进,DNS 等长间隔 UDP 应用会被误杀
#### A2. 后端生成 UDP forward 配置时强制设置 TTL
- **文件**: `go-backend/internal/http/handler/control_plane.go`
- **改动**: `buildForwardServiceConfigs` 中始终设置 `listener.metadata.ttl = "30s"`
- **原因**: 确保配置显式覆盖,不依赖 go-gost 默认值
#### A3. 后端隧道链服务配置加入 mux keepalive
- **文件**: `go-backend/internal/http/handler/mutations.go`
- **改动**: `buildTunnelChainServiceConfig` 中的 relay handler 加入 mux metadata:
```go
"mux.keepaliveInterval": "15s",
"mux.keepaliveTimeout": "45s",
```
### Part B: 新增 KCP 协议支持(新功能)
#### B1. 后端支持 `kcp` 作为隧道链传输协议
- **文件**: `go-backend/internal/http/handler/mutations.go`
- **改动**:
- `buildTunnelChainConfig`: 识别 `kcp` 协议,生成对应的 connector/dialer
- `buildTunnelChainServiceConfig`: 识别 `kcp` 协议,生成 KCP listener
- `isTLSTunnelProtocol` → `isTCPTunnelProtocol`(包含 TLS)
- KCP dialer 设置 `kcp.keepalive` 参数
- KCP 配置无需 `nodelay`(那是 TLS 特有)
#### B2. 前端支持选择 `kcp` 协议
- **文件**: `vite-frontend/src/pages/tunnel/` 相关表单
- **改动**: 协议选择器中加入 KCP 选项
#### B3. 确认 go-gost KCP 组件正常
- KCP dialer: `go-gost/x/dialer/kcp/` — 已存在
- KCP listener: `go-gost/x/listener/kcp/` — 已存在
- KCP connector: 使用 `relay` connector 通过 KCP dialer 连接
- 验证 KCP 配置的 metadata 参数传递正确
## 任务清单
- [x] A1: 增大 UDP listener 默认 TTL (5s→30s)
- [x] A2: 后端 forward 配置强制设置 UDP TTL=30s
- [x] A3: 后端隧道链 relay handler 加入 mux keepalive
- [x] B1: 后端支持 kcp 作为隧道链协议
- [x] B2: 前端协议选择器加入 KCP
- [x] B3: 验证 go-gost KCP 组件配置正确
- [x] C1: go-backend 合约测试 (187 passed)
- [x] C2: go-gost 编译验证 (passed)
- [x] C3: vite-frontend 编译验证 (passed)
## 文件变更清单
| 文件 | 变更类型 |
|------|----------|
| `go-gost/x/listener/udp/metadata.go` | 修改 defaultTTL: 5s→30s |
| `go-gost/x/listener/rudp/metadata.go` | 修改 defaultTTL: 5s→30s |
| `go-backend/internal/http/handler/control_plane.go` | buildForwardServiceConfigs: 强制设置 UDP TTL=30s, 移除 tunnelTLSProtocol 参数 |
| `go-backend/internal/http/handler/control_plane_test.go` | 更新测试调用签名 |
| `go-backend/internal/http/handler/mutations.go` | 新增 isTCPTunnelProtocol/isKCPTunnelProtocol/buildTunnelDialerConfig/buildTunnelListenerConfig; 隧道链配置加入 mux keepalive + KCP 支持 |
| `go-backend/internal/http/handler/federation.go` | federation 配置同步加入 mux keepalive + KCP 支持 |
| `vite-frontend/src/pages/tunnel.tsx` | 协议选择器新增 KCP 选项 (3 处)