Initial commit
This commit is contained in:
@@ -0,0 +1,523 @@
|
||||
# MeshRay 项目问题修复计划
|
||||
|
||||
**创建时间**: 2026-03-24
|
||||
**优先级**: P0 > P1 > P2
|
||||
**预计周期**: 2-3 周
|
||||
|
||||
---
|
||||
|
||||
## 📊 问题总览
|
||||
|
||||
| 优先级 | 数量 | 修复周期 | 风险等级 |
|
||||
|--------|------|----------|----------|
|
||||
| **P0 - 必须立即修复** | 5 | 2-3 天 | 🔴 极高 |
|
||||
| **P1 - 本迭代修复** | 6 | 3-4 天 | 🟠 高 |
|
||||
| **P2 - 下迭代修复** | 50+ | 1-2 周 | 🟡 中低 |
|
||||
|
||||
---
|
||||
|
||||
## 🔴 P0 - 必须立即修复(2-3 天)
|
||||
|
||||
### **问题 1: 使用 math/rand 生成密码**
|
||||
|
||||
**文件**: `internal/service/user.go:18`
|
||||
**风险**: 密码可预测,严重安全漏洞
|
||||
**修复方案**:
|
||||
|
||||
```go
|
||||
// ❌ 错误代码
|
||||
import "math/rand"
|
||||
password := string(rand.Intn(1000))
|
||||
|
||||
// ✅ 正确代码
|
||||
import "crypto/rand"
|
||||
b := make([]byte, 32)
|
||||
rand.Read(b)
|
||||
password := base64.StdEncoding.EncodeToString(b)
|
||||
```
|
||||
|
||||
**修复步骤**:
|
||||
1. 替换 import
|
||||
2. 使用 crypto/rand 生成随机字节
|
||||
3. Base64 编码为密码字符串
|
||||
4. 添加单元测试验证随机性
|
||||
|
||||
**预计时间**: 2 小时
|
||||
|
||||
---
|
||||
|
||||
### **问题 2: 固定模式生成加密密钥**
|
||||
|
||||
**文件**: `internal/config/config.go:153`
|
||||
**风险**: 所有实例使用相同密钥,完全无安全性
|
||||
**修复方案**:
|
||||
|
||||
```go
|
||||
// ❌ 错误代码
|
||||
key := []byte("meshray-secret-key-12345678") // 固定密钥
|
||||
|
||||
// ✅ 正确代码
|
||||
// 首次启动时生成随机密钥
|
||||
key := make([]byte, 32)
|
||||
if _, err := rand.Read(key); err != nil {
|
||||
return err
|
||||
}
|
||||
// 保存到配置文件或环境变量
|
||||
config.EncryptKey = base64.StdEncoding.EncodeToString(key)
|
||||
```
|
||||
|
||||
**修复步骤**:
|
||||
1. 检查配置文件中是否已有密钥
|
||||
2. 如无,则生成随机密钥并保存
|
||||
3. 如有,则读取使用
|
||||
4. 添加密钥轮换机制(可选)
|
||||
|
||||
**预计时间**: 4 小时
|
||||
|
||||
---
|
||||
|
||||
### **问题 3: Linux 特定命令跨平台不兼容**
|
||||
|
||||
**文件**: `internal/ctr/wg.go:378,464`
|
||||
**风险**: Windows/macOS 无法运行
|
||||
**修复方案**:
|
||||
|
||||
```go
|
||||
// ❌ 错误代码
|
||||
exec.Command("ip", "link", "add", name, "type", "wireguard")
|
||||
|
||||
// ✅ 正确代码(条件编译)
|
||||
// wg_linux.go
|
||||
// +build linux
|
||||
func createDevice(name string) error {
|
||||
exec.Command("ip", "link", "add", name, "type", "wireguard")
|
||||
}
|
||||
|
||||
// wg_windows.go
|
||||
// +build windows
|
||||
func createDevice(name string) error {
|
||||
// Windows 使用 wireguard.exe
|
||||
exec.Command("wireguard.exe", "/installtunnelservice", configPath)
|
||||
}
|
||||
|
||||
// wg_darwin.go
|
||||
// +build darwin
|
||||
func createDevice(name string) error {
|
||||
// macOS 使用 wg-go-tool
|
||||
exec.Command("wg-go-tool", "-c", configPath)
|
||||
}
|
||||
```
|
||||
|
||||
**修复步骤**:
|
||||
1. 创建 3 个平台特定文件
|
||||
2. 使用 build tag 区分
|
||||
3. 提取公共接口
|
||||
4. 测试各平台编译
|
||||
|
||||
**预计时间**: 1 天
|
||||
|
||||
---
|
||||
|
||||
### **问题 4: TUN 设备资源泄漏**
|
||||
|
||||
**文件**: `internal/ctr/wg.go:414-418`
|
||||
**风险**: 长时间运行后资源耗尽
|
||||
**修复方案**:
|
||||
|
||||
```go
|
||||
// ❌ 错误代码
|
||||
func (w *WGManager) createTUN() error {
|
||||
tun, err := tun.CreateTUN("wg0", mtu)
|
||||
// 未保存引用,后续无法关闭
|
||||
return nil
|
||||
}
|
||||
|
||||
// ✅ 正确代码
|
||||
type WGManager struct {
|
||||
tunDevices map[string]device.Device // 保存引用
|
||||
}
|
||||
|
||||
func (w *WGManager) createTUN() error {
|
||||
tun, err := tun.CreateTUN("wg0", mtu)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 保存引用
|
||||
w.tunDevices["wg0"] = tun
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *WGManager) Stop() error {
|
||||
// 关闭所有 TUN 设备
|
||||
for _, tun := range w.tunDevices {
|
||||
tun.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
```
|
||||
|
||||
**修复步骤**:
|
||||
1. 在 WGManager 中添加 tunDevices 字段
|
||||
2. 创建 TUN 后保存引用
|
||||
3. Stop() 方法中关闭所有设备
|
||||
4. 添加延迟测试验证无泄漏
|
||||
|
||||
**预计时间**: 4 小时
|
||||
|
||||
---
|
||||
|
||||
### **问题 5: wgDevice 未保存引用**
|
||||
|
||||
**文件**: `internal/ctr/wg.go:433`
|
||||
**风险**: 无法管理/关闭 WG 设备
|
||||
**修复方案**:
|
||||
|
||||
```go
|
||||
// ❌ 错误代码
|
||||
wgDevice, err := wgctrl.New()
|
||||
// 未保存,后续无法访问
|
||||
|
||||
// ✅ 正确代码
|
||||
type WGManager struct {
|
||||
wgClients map[string]*wgctrl.Client
|
||||
}
|
||||
|
||||
func (w *WGManager) initWG(deviceName string) error {
|
||||
client, err := wgctrl.New()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 保存引用
|
||||
w.wgClients[deviceName] = client
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *WGManager) Close() error {
|
||||
// 关闭所有 WG 客户端
|
||||
for _, client := range w.wgClients {
|
||||
client.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
```
|
||||
|
||||
**修复步骤**:
|
||||
1. 在 WGManager 中添加 wgClients 字段
|
||||
2. 创建 WG 客户端后保存引用
|
||||
3. Close() 方法统一关闭
|
||||
4. 添加单元测试验证
|
||||
|
||||
**预计时间**: 3 小时
|
||||
|
||||
---
|
||||
|
||||
## 🟠 P1 - 本迭代修复(3-4 天)
|
||||
|
||||
### **问题 6: ctr 初始化错误未返回**
|
||||
|
||||
**文件**: `internal/api/server.go:168`
|
||||
**风险**: ctrClient 为 nil 导致 panic
|
||||
**修复方案**:
|
||||
|
||||
```go
|
||||
// ❌ 错误代码
|
||||
ctrClient, err := ctr.NewClient(config)
|
||||
// 未检查 err
|
||||
|
||||
// ✅ 正确代码
|
||||
ctrClient, err := ctr.NewClient(config)
|
||||
if err != nil {
|
||||
log.Error("初始化 ctr 失败", zap.Error(err))
|
||||
return err // ← 返回错误,阻止启动
|
||||
}
|
||||
```
|
||||
|
||||
**预计时间**: 1 小时
|
||||
|
||||
---
|
||||
|
||||
### **问题 7: CreateNetwork 失败不回滚数据库**
|
||||
|
||||
**文件**: `internal/service/network.go:85-92`
|
||||
**风险**: 数据不一致
|
||||
**修复方案**:
|
||||
|
||||
```go
|
||||
// ❌ 错误代码
|
||||
func (s *NetworkService) CreateNetwork(req) error {
|
||||
network := &model.Network{...}
|
||||
s.store.DB().Create(network) // ← 保存
|
||||
|
||||
err = s.ctrClient.CreateNetwork(...)
|
||||
if err != nil {
|
||||
return err // ← 失败但未回滚!
|
||||
}
|
||||
}
|
||||
|
||||
// ✅ 正确代码
|
||||
func (s *NetworkService) CreateNetwork(req) error {
|
||||
tx := s.store.DB().Begin()
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
tx.Rollback()
|
||||
}
|
||||
}()
|
||||
|
||||
network := &model.Network{...}
|
||||
if err := tx.Create(network).Error; err != nil {
|
||||
tx.Rollback()
|
||||
return err
|
||||
}
|
||||
|
||||
err = s.ctrClient.CreateNetwork(...)
|
||||
if err != nil {
|
||||
tx.Rollback() // ← 回滚
|
||||
return fmt.Errorf("调用 ctr 失败:%w", err)
|
||||
}
|
||||
|
||||
return tx.Commit().Error
|
||||
}
|
||||
```
|
||||
|
||||
**预计时间**: 4 小时
|
||||
|
||||
---
|
||||
|
||||
### **问题 8: AddPeer 错误只记录不处理**
|
||||
|
||||
**文件**: `internal/service/device.go:115`
|
||||
**风险**: Peer 添加失败但用户以为成功
|
||||
**修复方案**:
|
||||
|
||||
```go
|
||||
// ❌ 错误代码
|
||||
err = s.ctrClient.AddPeer(...)
|
||||
if err != nil {
|
||||
log.Error("添加 Peer 失败", zap.Error(err))
|
||||
// 未返回错误!
|
||||
}
|
||||
|
||||
// ✅ 正确代码
|
||||
err = s.ctrClient.AddPeer(...)
|
||||
if err != nil {
|
||||
log.Error("添加 Peer 失败", zap.Error(err))
|
||||
return fmt.Errorf("添加设备失败:%w", err) // ← 返回错误
|
||||
}
|
||||
```
|
||||
|
||||
**预计时间**: 30 分钟
|
||||
|
||||
---
|
||||
|
||||
### **问题 9: 类型断言无检查**
|
||||
|
||||
**文件**: `internal/service/ddns.go:187`
|
||||
**风险**: 可能 panic
|
||||
**修复方案**:
|
||||
|
||||
```go
|
||||
// ❌ 错误代码
|
||||
provider := config.Provider.(DDNSProvider) // 可能 panic
|
||||
|
||||
// ✅ 正确代码
|
||||
provider, ok := config.Provider.(DDNSProvider)
|
||||
if !ok {
|
||||
return errors.New("无效的 DDNS Provider 类型")
|
||||
}
|
||||
```
|
||||
|
||||
**预计时间**: 30 分钟
|
||||
|
||||
---
|
||||
|
||||
### **问题 10: CORS 允许所有来源**
|
||||
|
||||
**文件**: `internal/api/middleware/auth.go:288`
|
||||
**风险**: CSRF 攻击
|
||||
**修复方案**:
|
||||
|
||||
```go
|
||||
// ❌ 错误代码
|
||||
middleware.AllowOrigin("*") // 允许所有来源
|
||||
|
||||
// ✅ 正确代码
|
||||
// 从配置读取允许的来源
|
||||
allowedOrigins := config.CORS.AllowedOrigins
|
||||
if len(allowedOrigins) == 0 {
|
||||
allowedOrigins = []string{"http://localhost:5173"}
|
||||
}
|
||||
|
||||
middleware.AllowOrigin(allowedOrigins...)
|
||||
```
|
||||
|
||||
**预计时间**: 2 小时
|
||||
|
||||
---
|
||||
|
||||
### **问题 11: Go 版本不存在**
|
||||
|
||||
**文件**: `go.mod`
|
||||
**风险**: 无法编译
|
||||
**修复方案**:
|
||||
|
||||
```diff
|
||||
- go 1.25.0
|
||||
+ go 1.21.0 # 使用最新稳定版
|
||||
```
|
||||
|
||||
**预计时间**: 10 分钟
|
||||
|
||||
---
|
||||
|
||||
## 🟡 P2 - 下迭代修复(1-2 周)
|
||||
|
||||
### **分类 1: 前端 API 未对接(30+ 处)**
|
||||
|
||||
**涉及文件**:
|
||||
- `web/src/views/Settings/*`
|
||||
- `web/src/views/Monitor/*`
|
||||
- `web/src/views/Networks/*`
|
||||
|
||||
**修复计划**:
|
||||
1. 第 1 周:完成 Settings 页面 API 对接
|
||||
2. 第 2 周:完成 Monitor 页面 API 对接
|
||||
3. 第 3 周:完成 Networks 页面 API 对接
|
||||
|
||||
**预计时间**: 1 周
|
||||
|
||||
---
|
||||
|
||||
### **分类 2: 后端功能未完成**
|
||||
|
||||
**待实现功能**:
|
||||
- [ ] DDNS 同步完整实现
|
||||
- [ ] MeshSeed 生成和解析
|
||||
- [ ] Watchdog 监控机制
|
||||
- [ ] 告警规则引擎
|
||||
- [ ] 审计日志导出
|
||||
|
||||
**预计时间**: 3-4 天
|
||||
|
||||
---
|
||||
|
||||
### **分类 3: 并发安全问题**
|
||||
|
||||
**涉及文件**:
|
||||
- `core/connect/strategy.go` - channel 锁保护
|
||||
- `internal/ctr/wg.go` - 并发访问保护
|
||||
|
||||
**修复方案**:
|
||||
```go
|
||||
type StrategyScheduler struct {
|
||||
mu sync.RWMutex
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
**预计时间**: 1 天
|
||||
|
||||
---
|
||||
|
||||
### **分类 4: 依赖清理**
|
||||
|
||||
**未使用的依赖**:
|
||||
```diff
|
||||
- github.com/some/unused-package v1.0.0
|
||||
- github.com/another/unused v2.0.0
|
||||
```
|
||||
|
||||
**修复步骤**:
|
||||
1. 使用 `go mod why` 确认是否使用
|
||||
2. 删除未使用的依赖
|
||||
3. 运行 `go mod tidy`
|
||||
|
||||
**预计时间**: 2 小时
|
||||
|
||||
---
|
||||
|
||||
## 📋 详细时间表
|
||||
|
||||
### **第 1 周:P0 修复**
|
||||
|
||||
| 时间 | 任务 | 负责人 |
|
||||
|------|------|--------|
|
||||
| Day 1 AM | 问题 1: 随机数生成修复 | Dev A |
|
||||
| Day 1 PM | 问题 2: 加密密钥修复 | Dev A |
|
||||
| Day 2 AM | 问题 3: 跨平台兼容 | Dev B |
|
||||
| Day 2 PM | 问题 4: TUN 设备引用 | Dev B |
|
||||
| Day 3 AM | 问题 5: wgDevice 引用 | Dev B |
|
||||
| Day 3 PM | 测试验证 | QA |
|
||||
|
||||
### **第 2 周:P1 修复**
|
||||
|
||||
| 时间 | 任务 | 负责人 |
|
||||
|------|------|--------|
|
||||
| Day 1 | 问题 6-8: 错误处理 | Dev A |
|
||||
| Day 2 | 问题 9-10: 类型安全和 CORS | Dev B |
|
||||
| Day 3 | 问题 11: Go 版本 + 回归测试 | Dev A + QA |
|
||||
|
||||
### **第 3-4 周:P2 修复**
|
||||
|
||||
| 时间 | 任务 | 负责人 |
|
||||
|------|------|--------|
|
||||
| Week 3 | 前端 API 对接(Settings) | Frontend |
|
||||
| Week 4 | 前端 API 对接(Monitor) | Frontend |
|
||||
| Week 4 | 后端功能完善 | Backend |
|
||||
|
||||
---
|
||||
|
||||
## ✅ 验收标准
|
||||
|
||||
### **P0 修复验收**
|
||||
- [ ] 密码生成通过 NIST 随机性测试
|
||||
- [ ] 加密密钥每个实例唯一
|
||||
- [ ] Windows/macOS/Linux 均能编译运行
|
||||
- [ ] 72 小时运行无资源泄漏
|
||||
- [ ] WG 设备正常启停
|
||||
|
||||
### **P1 修复验收**
|
||||
- [ ] 所有错误都有返回和日志
|
||||
- [ ] 数据库事务回滚测试通过
|
||||
- [ ] CORS 配置化且默认安全
|
||||
- [ ] 编译无警告
|
||||
|
||||
### **P2 修复验收**
|
||||
- [ ] 前端 API 对接率 > 90%
|
||||
- [ ] 核心功能完整可用
|
||||
- [ ] 并发测试无 race condition
|
||||
- [ ] 依赖列表精简
|
||||
|
||||
---
|
||||
|
||||
## 🎯 风险控制
|
||||
|
||||
### **高风险项**
|
||||
1. **跨平台兼容性** - 需要实际测试环境
|
||||
- 缓解:使用 GitHub Actions CI/CD
|
||||
|
||||
2. **资源泄漏** - 难以复现
|
||||
- 缓解:压力测试 + 内存分析
|
||||
|
||||
3. **数据库回滚** - 影响现有逻辑
|
||||
- 缓解:充分的单元测试
|
||||
|
||||
---
|
||||
|
||||
## 📊 进度跟踪
|
||||
|
||||
使用 GitHub Projects 跟踪:
|
||||
- P0 Issues: 5 个
|
||||
- P1 Issues: 6 个
|
||||
- P2 Issues: 50+ 个
|
||||
|
||||
**每日站会**同步进度,**每周五**演示修复成果。
|
||||
|
||||
---
|
||||
|
||||
*创建时间:2026-03-24*
|
||||
*版本:v1.0*
|
||||
*下次更新:完成 P0 修复后*
|
||||
Reference in New Issue
Block a user