All checks were successful
Build Multi-Platform Binaries / build-frontend (push) Successful in 38s
Build Multi-Platform Binaries / build-binaries (amd64, darwin, server, false) (push) Successful in 59s
Build Multi-Platform Binaries / build-binaries (amd64, linux, client, true) (push) Successful in 1m8s
Build Multi-Platform Binaries / build-binaries (amd64, linux, server, true) (push) Successful in 1m17s
Build Multi-Platform Binaries / build-binaries (amd64, windows, client, true) (push) Successful in 53s
Build Multi-Platform Binaries / build-binaries (amd64, windows, server, true) (push) Successful in 1m14s
Build Multi-Platform Binaries / build-binaries (arm, 7, linux, client, true) (push) Successful in 2m8s
Build Multi-Platform Binaries / build-binaries (arm, 7, linux, server, true) (push) Successful in 1m10s
Build Multi-Platform Binaries / build-binaries (arm64, darwin, server, false) (push) Successful in 57s
Build Multi-Platform Binaries / build-binaries (arm64, linux, client, true) (push) Successful in 58s
Build Multi-Platform Binaries / build-binaries (arm64, linux, server, true) (push) Successful in 1m11s
Build Multi-Platform Binaries / build-binaries (arm64, windows, server, false) (push) Successful in 55s
320 lines
11 KiB
Markdown
320 lines
11 KiB
Markdown
# GoTunnel 重构计划
|
||
|
||
## 概述
|
||
|
||
本次重构包含三个主要目标:
|
||
1. 移除 WASM 支持,只保留 JS 插件系统
|
||
2. 优化 Web 界面,支持协议动态配置和 JS 插件管理
|
||
3. 实现动态重启客户端和插件功能
|
||
|
||
---
|
||
|
||
## 第一部分:移除 WASM,简化插件系统
|
||
|
||
### 1.1 需要删除的文件/目录
|
||
- `pkg/plugin/wasm/` - WASM 运行时目录(如果存在)
|
||
|
||
### 1.2 需要修改的文件
|
||
|
||
#### 数据库层 (`internal/server/db/`)
|
||
- **interface.go**: 移除 `PluginStore` 接口中的 `GetPluginWASM` 方法
|
||
- **sqlite.go**:
|
||
- 移除 `plugins` 表(WASM 插件表)
|
||
- 移除相关的 CRUD 方法
|
||
- 保留 `js_plugins` 表
|
||
|
||
#### 插件类型 (`pkg/plugin/types.go`)
|
||
- 移除 `PluginSource` 中的 `"wasm"` 选项,只保留 `"builtin"` 和 `"script"`
|
||
|
||
#### 依赖清理
|
||
- 检查 `go.mod` 是否有 wazero 依赖,如有则移除
|
||
|
||
---
|
||
|
||
## 第二部分:优化 Web 界面
|
||
|
||
### 2.1 协议动态配置
|
||
|
||
#### 后端修改
|
||
|
||
##### A. 扩展 ConfigField 类型 (`pkg/plugin/types.go`)
|
||
```go
|
||
type ConfigField struct {
|
||
Key string `json:"key"`
|
||
Label string `json:"label"`
|
||
Type string `json:"type"` // string, number, bool, select, password
|
||
Default string `json:"default,omitempty"`
|
||
Required bool `json:"required,omitempty"`
|
||
Options []string `json:"options,omitempty"`
|
||
Description string `json:"description,omitempty"`
|
||
}
|
||
|
||
type RuleSchema struct {
|
||
NeedsLocalAddr bool `json:"needs_local_addr"`
|
||
ExtraFields []ConfigField `json:"extra_fields"`
|
||
}
|
||
```
|
||
|
||
##### B. 内置协议配置模式
|
||
为 SOCKS5 和 HTTP 代理添加认证配置字段:
|
||
|
||
```go
|
||
// SOCKS5 配置模式
|
||
var Socks5Schema = RuleSchema{
|
||
NeedsLocalAddr: false,
|
||
ExtraFields: []ConfigField{
|
||
{Key: "auth_enabled", Label: "启用认证", Type: "bool", Default: "false"},
|
||
{Key: "username", Label: "用户名", Type: "string"},
|
||
{Key: "password", Label: "密码", Type: "password"},
|
||
},
|
||
}
|
||
|
||
// HTTP 代理配置模式
|
||
var HTTPProxySchema = RuleSchema{
|
||
NeedsLocalAddr: false,
|
||
ExtraFields: []ConfigField{
|
||
{Key: "auth_enabled", Label: "启用认证", Type: "bool", Default: "false"},
|
||
{Key: "username", Label: "用户名", Type: "string"},
|
||
{Key: "password", Label: "密码", Type: "password"},
|
||
},
|
||
}
|
||
```
|
||
|
||
##### C. API 端点 (`internal/server/router/api.go`)
|
||
- **GET `/api/rule-schemas`**: 返回所有协议类型的配置模式
|
||
- 内置类型 (tcp, udp, http, https) 的模式
|
||
- 已注册插件的模式(从插件 Metadata 获取)
|
||
|
||
#### 前端修改 (`web/src/views/ClientView.vue`)
|
||
- 页面加载时获取 rule-schemas
|
||
- 根据选择的协议类型动态渲染额外配置字段
|
||
- 支持的字段类型:string, number, bool, select, password
|
||
|
||
### 2.2 JS 插件管理界面优化
|
||
|
||
#### 后端修改
|
||
|
||
##### A. 扩展 JSPlugin 结构 (`internal/server/db/interface.go`)
|
||
```go
|
||
type JSPlugin struct {
|
||
Name string `json:"name"`
|
||
Source string `json:"source"` // JS 源码
|
||
Signature string `json:"signature"` // 官方签名
|
||
Description string `json:"description"`
|
||
Author string `json:"author"`
|
||
Version string `json:"version"`
|
||
AutoPush []string `json:"auto_push"` // 自动推送客户端列表
|
||
Config map[string]string `json:"config"` // 插件运行时配置
|
||
ConfigSchema []ConfigField `json:"config_schema"` // 配置字段定义
|
||
AutoStart bool `json:"auto_start"`
|
||
Enabled bool `json:"enabled"`
|
||
CreatedAt time.Time `json:"created_at"`
|
||
UpdatedAt time.Time `json:"updated_at"`
|
||
}
|
||
```
|
||
|
||
##### B. 新增/修改 API 端点
|
||
- **GET `/api/js-plugins`**: 获取所有 JS 插件列表(包含配置模式)
|
||
- **GET `/api/js-plugin/{name}`**: 获取单个插件详情
|
||
- **PUT `/api/js-plugin/{name}/config`**: 更新插件运行时配置
|
||
- **POST `/api/js-plugin/{name}/push/{clientId}`**: 推送插件到指定客户端
|
||
- **POST `/api/js-plugin/{name}/reload`**: 重新加载插件(重新解析源码)
|
||
|
||
#### 前端修改 (`web/src/views/PluginsView.vue`)
|
||
|
||
##### A. 重新设计 JS 插件 Tab
|
||
```
|
||
┌─────────────────────────────────────────────────────────────┐
|
||
│ 已安装的 JS 插件 │
|
||
├─────────────────────────────────────────────────────────────┤
|
||
│ ┌─────────────────────────────────────────────────────────┐ │
|
||
│ │ 📦 socks5-auth v1.0.0 │ │
|
||
│ │ 带认证的 SOCKS5 代理 │ │
|
||
│ │ 作者: official │ │
|
||
│ │ ────────────────────────────────────────────────────── │ │
|
||
│ │ 状态: ✅ 启用 自动启动: ✅ │ │
|
||
│ │ 推送目标: 所有客户端 │ │
|
||
│ │ ────────────────────────────────────────────────────── │ │
|
||
│ │ [⚙️ 配置] [🔄 重载] [📤 推送] [🗑️ 删除] │ │
|
||
│ └─────────────────────────────────────────────────────────┘ │
|
||
└─────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
##### B. 插件配置模态框
|
||
- 动态渲染 ConfigSchema 定义的字段
|
||
- 支持 string, number, bool, select, password 类型
|
||
- 保存后可选择是否同步到已连接的客户端
|
||
|
||
##### C. 推送配置
|
||
- 选择目标客户端(支持多选)
|
||
- 选择是否自动启动
|
||
- 显示推送结果
|
||
|
||
---
|
||
|
||
## 第三部分:动态重启功能
|
||
|
||
### 3.1 协议消息定义 (`pkg/protocol/message.go`)
|
||
|
||
```go
|
||
// 已有消息类型
|
||
const (
|
||
MsgTypeClientPluginStart = 40 // 启动插件
|
||
MsgTypeClientPluginStop = 41 // 停止插件 (需实现)
|
||
MsgTypeClientPluginStatus = 42 // 插件状态
|
||
MsgTypeClientPluginConn = 43 // 插件连接
|
||
|
||
// 新增消息类型
|
||
MsgTypeClientRestart = 44 // 客户端重启
|
||
MsgTypePluginConfigUpdate = 45 // 插件配置更新
|
||
)
|
||
|
||
// 新增请求/响应结构
|
||
type ClientPluginStopRequest struct {
|
||
PluginName string `json:"plugin_name"`
|
||
RuleName string `json:"rule_name"`
|
||
}
|
||
|
||
type ClientRestartRequest struct {
|
||
Reason string `json:"reason,omitempty"`
|
||
}
|
||
|
||
type PluginConfigUpdateRequest struct {
|
||
PluginName string `json:"plugin_name"`
|
||
RuleName string `json:"rule_name"`
|
||
Config map[string]string `json:"config"`
|
||
}
|
||
```
|
||
|
||
### 3.2 客户端实现 (`internal/client/tunnel/client.go`)
|
||
|
||
#### A. 实现插件停止处理
|
||
```go
|
||
func (c *Client) handleClientPluginStop(stream net.Conn, msg *protocol.Message) {
|
||
defer stream.Close()
|
||
|
||
var req protocol.ClientPluginStopRequest
|
||
if err := msg.ParsePayload(&req); err != nil {
|
||
return
|
||
}
|
||
|
||
key := req.PluginName + ":" + req.RuleName
|
||
|
||
c.pluginMu.Lock()
|
||
if handler, ok := c.runningPlugins[key]; ok {
|
||
handler.Stop()
|
||
delete(c.runningPlugins, key)
|
||
}
|
||
c.pluginMu.Unlock()
|
||
|
||
// 发送确认
|
||
resp := protocol.ClientPluginStatusResponse{
|
||
PluginName: req.PluginName,
|
||
RuleName: req.RuleName,
|
||
Running: false,
|
||
}
|
||
respMsg, _ := protocol.NewMessage(protocol.MsgTypeClientPluginStatus, resp)
|
||
protocol.WriteMessage(stream, respMsg)
|
||
}
|
||
```
|
||
|
||
#### B. 实现配置热更新
|
||
```go
|
||
func (c *Client) handlePluginConfigUpdate(stream net.Conn, msg *protocol.Message) {
|
||
// 更新运行中插件的配置(如果插件支持热更新)
|
||
}
|
||
```
|
||
|
||
#### C. 实现客户端优雅重启
|
||
```go
|
||
func (c *Client) handleClientRestart(stream net.Conn, msg *protocol.Message) {
|
||
// 1. 停止所有运行中的插件
|
||
// 2. 关闭当前会话
|
||
// 3. 触发重连(Run() 循环会自动处理)
|
||
}
|
||
```
|
||
|
||
### 3.3 服务端实现 (`internal/server/tunnel/server.go`)
|
||
|
||
```go
|
||
// 停止客户端插件
|
||
func (s *Server) StopClientPlugin(clientID, pluginName, ruleName string) error
|
||
|
||
// 重启客户端插件
|
||
func (s *Server) RestartClientPlugin(clientID, pluginName, ruleName string) error
|
||
|
||
// 更新插件配置
|
||
func (s *Server) UpdateClientPluginConfig(clientID, pluginName, ruleName string, config map[string]string) error
|
||
|
||
// 重启整个客户端
|
||
func (s *Server) RestartClient(clientID string) error
|
||
```
|
||
|
||
### 3.4 REST API (`internal/server/router/api.go`)
|
||
|
||
```go
|
||
// 客户端控制
|
||
POST /api/client/{id}/restart // 重启整个客户端
|
||
|
||
// 插件控制
|
||
POST /api/client/{id}/plugin/{name}/stop // 停止插件
|
||
POST /api/client/{id}/plugin/{name}/restart // 重启插件
|
||
PUT /api/client/{id}/plugin/{name}/config // 更新配置并可选重启
|
||
```
|
||
|
||
### 3.5 前端界面 (`web/src/views/ClientView.vue`)
|
||
|
||
在客户端详情页添加控制按钮:
|
||
- **客户端级别**: "重启客户端" 按钮
|
||
- **插件级别**: 每个运行中的插件显示 "停止"、"重启"、"配置" 按钮
|
||
|
||
---
|
||
|
||
## 实施顺序
|
||
|
||
### 阶段 1: 清理 WASM 代码
|
||
1. 删除 WASM 相关文件和代码
|
||
2. 更新数据库 schema
|
||
3. 清理依赖
|
||
|
||
### 阶段 2: 协议动态配置
|
||
1. 定义 ConfigField 和 RuleSchema 类型
|
||
2. 实现内置协议的配置模式
|
||
3. 添加 `/api/rule-schemas` 端点
|
||
4. 更新前端规则编辑界面
|
||
|
||
### 阶段 3: JS 插件管理优化
|
||
1. 扩展 JSPlugin 结构和数据库
|
||
2. 实现插件配置 API
|
||
3. 重新设计前端插件管理界面
|
||
|
||
### 阶段 4: 动态重启功能
|
||
1. 实现客户端 pluginStop 处理
|
||
2. 实现服务端重启方法
|
||
3. 添加 REST API 端点
|
||
4. 更新前端添加控制按钮
|
||
|
||
### 阶段 5: 测试和文档
|
||
1. 端到端测试
|
||
2. 更新 CLAUDE.md
|
||
|
||
---
|
||
|
||
## 文件变更清单
|
||
|
||
### 后端 Go 文件
|
||
- `pkg/plugin/types.go` - 添加 ConfigField, RuleSchema
|
||
- `pkg/plugin/schema.go` (新建) - 内置协议配置模式
|
||
- `pkg/protocol/message.go` - 新增消息类型
|
||
- `internal/server/db/interface.go` - 更新接口
|
||
- `internal/server/db/sqlite.go` - 更新数据库操作
|
||
- `internal/server/router/api.go` - 新增 API 端点
|
||
- `internal/server/tunnel/server.go` - 重启控制方法
|
||
- `internal/client/tunnel/client.go` - 插件停止/重启处理
|
||
|
||
### 前端文件
|
||
- `web/src/types/index.ts` - 类型定义
|
||
- `web/src/api/index.ts` - API 调用
|
||
- `web/src/views/ClientView.vue` - 规则配置和重启控制
|
||
- `web/src/views/PluginsView.vue` - 插件管理界面
|