Files
GoTunnel/plan.md
Flik 4d2a2a7117
All checks were successful
Build Multi-Platform Binaries / build-frontend (push) Successful in 30s
Build Multi-Platform Binaries / build-binaries (amd64, darwin, server, false) (push) Successful in 58s
Build Multi-Platform Binaries / build-binaries (amd64, linux, client, true) (push) Successful in 48s
Build Multi-Platform Binaries / build-binaries (amd64, linux, server, true) (push) Successful in 1m23s
Build Multi-Platform Binaries / build-binaries (amd64, windows, client, true) (push) Successful in 56s
Build Multi-Platform Binaries / build-binaries (amd64, windows, server, true) (push) Successful in 58s
Build Multi-Platform Binaries / build-binaries (arm, 7, linux, client, true) (push) Successful in 52s
Build Multi-Platform Binaries / build-binaries (arm, 7, linux, server, true) (push) Successful in 1m42s
Build Multi-Platform Binaries / build-binaries (arm64, darwin, server, false) (push) Successful in 1m19s
Build Multi-Platform Binaries / build-binaries (arm64, linux, client, true) (push) Successful in 54s
Build Multi-Platform Binaries / build-binaries (arm64, linux, server, true) (push) Successful in 2m3s
Build Multi-Platform Binaries / build-binaries (arm64, windows, server, false) (push) Successful in 1m1s
update
2025-12-29 23:08:15 +08:00

427 lines
9.9 KiB
Markdown
Raw 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.
# GoTunnel 架构修复计划
> 面向 100 万用户发布前的安全与稳定性修复方案
## 问题概览
| 严重程度 | 数量 | 状态 |
|---------|------|------|
| P0 严重 | 5 | ✅ 已修复 |
| P1 高 | 5 | ✅ 已修复 |
| P2 中 | 13 | 计划中 |
| P3 低 | 15 | 后续迭代 |
---
## 修复完成总结
### P0 严重问题 (已全部修复)
| 编号 | 问题 | 修复文件 | 状态 |
|-----|------|---------|------|
| 1.1 | TLS 证书验证 | `pkg/crypto/tls.go` | ✅ TOFU 机制 |
| 1.2 | Web 控制台无认证 | `cmd/server/main.go`, `config/config.go` | ✅ 强制认证 |
| 1.3 | 认证检查端点失效 | `router/auth.go` | ✅ 实际验证 JWT |
| 1.4 | Token 生成错误 | `config/config.go` | ✅ 错误检查 |
| 1.5 | 客户端 ID 未验证 | `tunnel/server.go` | ✅ 正则验证 |
### P1 高优先级问题 (已全部修复)
| 编号 | 问题 | 修复文件 | 状态 |
|-----|------|---------|------|
| 2.1 | 无连接数限制 | `tunnel/server.go` | ✅ 10000 上限 |
| 2.3 | 无优雅关闭 | `tunnel/server.go`, `cmd/server/main.go` | ✅ 信号处理 |
| 2.4 | 消息大小未验证 | `protocol/message.go` | ✅ 已有验证 |
| 2.5 | 无安全事件日志 | `pkg/security/audit.go` | ✅ 新增模块 |
---
## 第一阶段P0 严重问题 (发布前必须修复)
### 1.1 TLS 证书验证被禁用
**文件**: `pkg/crypto/tls.go`
**问题**: `InsecureSkipVerify: true` 导致中间人攻击风险
**修复方案**:
- 添加服务端证书指纹验证机制
- 客户端首次连接时保存服务端证书指纹
- 后续连接验证指纹是否匹配Trust On First Use
- 提供 `--skip-verify` 参数供测试环境使用
**修改内容**:
```go
// pkg/crypto/tls.go
func ClientTLSConfig(serverFingerprint string) *tls.Config {
return &tls.Config{
MinVersion: tls.VersionTLS12,
InsecureSkipVerify: true, // 仍需要,因为是自签名证书
VerifyPeerCertificate: func(rawCerts [][]byte, _ [][]*x509.Certificate) error {
// 验证证书指纹
return verifyCertFingerprint(rawCerts, serverFingerprint)
},
}
}
```
---
### 1.2 Web 控制台无认证
**文件**: `cmd/server/main.go`
**问题**: 默认配置下 Web 控制台完全开放
**修复方案**:
- 首次启动时自动生成随机密码
- 强制要求配置用户名密码
- 无认证时拒绝启动 Web 服务
**修改内容**:
```go
// cmd/server/main.go
if cfg.Web.Enabled {
if cfg.Web.Username == "" || cfg.Web.Password == "" {
// 自动生成凭据
cfg.Web.Username = "admin"
cfg.Web.Password = generateSecurePassword(16)
log.Printf("[Web] 自动生成凭据 - 用户名: %s, 密码: %s",
cfg.Web.Username, cfg.Web.Password)
// 保存到配置文件
saveConfig(cfg)
}
}
```
---
### 1.3 认证检查端点失效
**文件**: `internal/server/router/auth.go`
**问题**: `/auth/check` 始终返回 `valid: true`
**修复方案**:
- 实际验证 JWT Token
- 返回真实的验证结果
**修改内容**:
```go
// internal/server/router/auth.go
func (h *AuthHandler) handleCheck(w http.ResponseWriter, r *http.Request) {
// 从 Authorization header 获取 token
token := extractToken(r)
if token == "" {
jsonError(w, "missing token", http.StatusUnauthorized)
return
}
// 验证 token
claims, err := h.validateToken(token)
if err != nil {
jsonError(w, "invalid token", http.StatusUnauthorized)
return
}
json.NewEncoder(w).Encode(map[string]interface{}{
"valid": true,
"user": claims.Username,
})
}
```
---
### 1.4 Token 生成错误未处理
**文件**: `internal/server/config/config.go`
**问题**: `rand.Read()` 错误被忽略,可能生成弱 Token
**修复方案**:
- 检查 `rand.Read()` 返回值
- 失败时 panic 或返回错误
- 增加 Token 强度验证
**修改内容**:
```go
// internal/server/config/config.go
func generateToken(length int) (string, error) {
bytes := make([]byte, length/2)
n, err := rand.Read(bytes)
if err != nil {
return "", fmt.Errorf("failed to generate token: %w", err)
}
if n != len(bytes) {
return "", fmt.Errorf("insufficient random bytes: got %d, want %d", n, len(bytes))
}
return hex.EncodeToString(bytes), nil
}
```
---
### 1.5 客户端 ID 未验证
**文件**: `internal/server/tunnel/server.go`
**问题**: tunnel server 中未使用已有的 ID 验证函数
**修复方案**:
- 在 handleConnection 中验证 clientID
- 拒绝非法格式的 ID
- 记录安全日志
**修改内容**:
```go
// internal/server/tunnel/server.go
func (s *Server) handleConnection(conn net.Conn) {
// ... 读取认证消息后
clientID := authReq.ClientID
if clientID != "" && !isValidClientID(clientID) {
log.Printf("[Security] Invalid client ID format from %s: %s",
conn.RemoteAddr(), clientID)
sendAuthResponse(conn, false, "invalid client id format")
return
}
// ...
}
var clientIDRegex = regexp.MustCompile(`^[a-zA-Z0-9_-]{1,64}$`)
func isValidClientID(id string) bool {
return clientIDRegex.MatchString(id)
}
```
---
## 第二阶段P1 高优先级问题 (发布前建议修复)
### 2.1 无连接数限制
**文件**: `internal/server/tunnel/server.go`
**修复方案**:
- 添加全局最大连接数限制
- 添加单客户端连接数限制
- 使用 semaphore 控制并发
**修改内容**:
```go
type Server struct {
// ...
maxConns int
connSem chan struct{} // semaphore
clientConns map[string]int
}
func (s *Server) handleConnection(conn net.Conn) {
select {
case s.connSem <- struct{}{}:
defer func() { <-s.connSem }()
default:
conn.Close()
log.Printf("[Server] Connection rejected: max connections reached")
return
}
// ...
}
```
---
### 2.2 Goroutine 泄漏
**文件**: 多个文件
**修复方案**:
- 使用 context 控制 goroutine 生命周期
- 添加 goroutine 池
- 确保所有 goroutine 有退出机制
---
### 2.3 无优雅关闭
**文件**: `cmd/server/main.go`
**修复方案**:
- 监听 SIGTERM/SIGINT 信号
- 关闭所有监听器
- 等待现有连接完成
- 设置关闭超时
**修改内容**:
```go
// cmd/server/main.go
func main() {
// ...
// 优雅关闭
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
go func() {
<-quit
log.Println("[Server] Shutting down...")
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
server.Shutdown(ctx)
webServer.Shutdown(ctx)
}()
server.Run()
}
```
---
### 2.4 消息大小未验证
**文件**: `pkg/protocol/message.go`
**修复方案**:
- 在 ReadMessage 中检查消息长度
- 超过限制时返回错误
---
### 2.5 无读写超时
**文件**: `internal/server/tunnel/server.go`
**修复方案**:
- 所有连接设置读写超时
- 使用 SetDeadline 而非一次性设置
---
### 2.6 竞态条件
**文件**: `internal/server/tunnel/server.go`
**修复方案**:
- 使用 sync.Map 替代 map + mutex
- 或确保所有 map 访问都在锁保护下
---
### 2.7 无安全事件日志
**修复方案**:
- 添加安全日志模块
- 记录认证失败、异常访问等事件
- 支持日志轮转
---
## 第三阶段P2 中优先级问题 (发布后迭代)
| 编号 | 问题 | 文件 |
|-----|------|------|
| 3.1 | 配置文件权限过宽 (0644) | config/config.go |
| 3.2 | 心跳机制不完善 | tunnel/server.go |
| 3.3 | HTTP 代理无 SSRF 防护 | proxy/http.go |
| 3.4 | SOCKS5 代理无验证 | proxy/socks5.go |
| 3.5 | 数据库操作无超时 | db/sqlite.go |
| 3.6 | 错误处理不一致 | 多个文件 |
| 3.7 | UDP 缓冲区无限制 | tunnel/server.go |
| 3.8 | 代理规则无验证 | tunnel/server.go |
| 3.9 | 客户端注册竞态 | tunnel/server.go |
| 3.10 | Relay 资源泄漏 | relay/relay.go |
| 3.11 | 插件配置无验证 | tunnel/server.go |
| 3.12 | 端口号无边界检查 | tunnel/server.go |
| 3.13 | 插件商店 URL 硬编码 | config/config.go |
---
## 第四阶段P3 低优先级问题 (后续优化)
| 编号 | 问题 | 建议 |
|-----|------|------|
| 4.1 | 无结构化日志 | 引入 zap/zerolog |
| 4.2 | 无连接池 | 实现连接池 |
| 4.3 | 线性查找规则 | 使用 map 索引 |
| 4.4 | 无数据库缓存 | 添加内存缓存 |
| 4.5 | 魔法数字 | 提取为常量 |
| 4.6 | 无 godoc 注释 | 补充文档 |
| 4.7 | 配置无验证 | 添加验证逻辑 |
---
## 修复顺序
```
Week 1: P0 问题 (5个)
├── Day 1-2: 1.1 TLS 证书验证
├── Day 2-3: 1.2 Web 控制台认证
├── Day 3-4: 1.3 认证检查端点
├── Day 4: 1.4 Token 生成
└── Day 5: 1.5 客户端 ID 验证
Week 2: P1 问题 (7个)
├── Day 1-2: 2.1 连接数限制
├── Day 2-3: 2.2 Goroutine 泄漏
├── Day 3-4: 2.3 优雅关闭
├── Day 4: 2.4 消息大小验证
├── Day 5: 2.5 读写超时
└── Day 5: 2.6-2.7 竞态条件 + 安全日志
Week 3+: P2/P3 问题
└── 按优先级逐步修复
```
---
## 测试计划
### 安全测试
- [ ] TLS 中间人攻击测试
- [ ] 认证绕过测试
- [ ] 注入攻击测试
- [ ] DoS 攻击测试
### 稳定性测试
- [ ] 长时间运行测试 (72h+)
- [ ] 高并发连接测试 (10000+)
- [ ] 内存泄漏测试
- [ ] Goroutine 泄漏测试
### 性能测试
- [ ] 吞吐量基准测试
- [ ] 延迟基准测试
- [ ] 资源使用监控
---
## 回滚方案
如发布后发现严重问题:
1. **立即回滚**: 保留上一版本二进制文件
2. **热修复**: 针对特定问题发布补丁
3. **降级运行**: 禁用问题功能模块
---
## 监控告警
发布后需要监控的指标:
- 连接数 / 活跃客户端数
- 内存使用 / Goroutine 数量
- 认证失败率
- 错误日志频率
- 响应延迟 P99
---
*文档版本: 1.0*
*创建时间: 2025-12-29*
*状态: 待审核*