Initial commit

This commit is contained in:
2026-06-30 15:14:37 +08:00
commit 15dab96872
311 changed files with 95639 additions and 0 deletions
+515
View File
@@ -0,0 +1,515 @@
# MeshRay - 去中心化 P2P 组网平台
## 项目简介
MeshRay 是一个基于 WireGuard 的去中心化 P2P 组网平台,支持 STUN/TURN 穿透、9 层降级传输策略、Mesh 中继等高级功能。采用 **单进程单端口** 架构部署,ctr 调度中心与 Core 建连层通过直接函数调用集成(无需 gRPC)。
### 核心特性
-**去中心化架构**:无中心服务器,设备间直接 P2P 通信
-**智能穿透**STUN + TURN 自动打洞,支持多种 NAT 类型
-**9 层降级传输**:从 Direct-UDP 到 WS/WSS,链路不通自动切换
-**Mesh 中继**:支持设备间中继转发,突破网络限制
-**安全加密**WireGuard 官方库 + Ed25519 签名 + AES-256-GCM
-**DDNS 动态域名**:支持 Cloudflare、阿里云、腾讯云 DNS 自动同步
-**Web 管理面板**:Go embed 内嵌静态资源,单文件部署
-**完整通知系统**WebSocket 实时推送 + 持久化存储
### 核心术语
| 术语 | 含义 | 说明 |
|------|------|------|
| **ctr** | MeshRay-Control | 调度中心,负责 WG 设备管理和信令中转 |
| **Core** | MeshRay-Core | 建连层,负责点对点传输 |
| **Route ID** | 路由标识 | 派生自 peerKey 的哈希值,用于 Relay 数据转发 |
| **MeshSeed** | 组网凭证 | 加密的组网配置载体(含 NetworkSecret |
| **NetworkID** | 组网 ID | 雪花算法生成的唯一标识(uint64) |
| **Bind** | 绑定接口 | Engine 为 Peer 开启本地监听端口,截获 WG 密文包 |
| **Layer** | 传输层 | 9 种传输协议之一(如 Direct-UDP、TURN-TCP |
| **WG 设备** | WireGuard Interface | wg0/wg1 等虚拟网卡,由 wgctrl 管理 |
| **AllowedIPs** | WG 路由表 | WireGuard 的路由规则,决定哪些流量走 WG 隧道 |
### 快速开始
```bash
# 克隆项目
git clone https://git.zkcoi.com/zkcoi/meshray.git
# 安装 Go 依赖
go mod download
# 直接编译运行
go build -o meshray.exe ./cmd/meshray
./meshray.exe
# 访问管理后台
http://localhost:9531
```
> **注意**:前端已内嵌到 Go 二进制中,无需单独编译前端或安装 Node.js。
---
## 核心架构
### 项目目录结构
```
meshray/
├── cmd/ # 可执行文件入口
│ ├── meshray/ # 主程序(Windows 服务 + 系统托盘)
│ ├── checkdb/ # 数据库检查工具
│ ├── reset-password/ # 管理员密码重置工具
│ └── testembed/ # Embed 测试工具
├── core/ # MeshRay-Core 模块(建连层)
│ ├── connect/ # 9 层传输工厂
│ │ ├── strategy.go # 策略调度器
│ │ ├── direct.go # Direct-UDP 直连
│ │ ├── fake_tcp.go # FakeTCP 连接实现
│ │ ├── real_tcp.go # RealTCP 连接实现
│ │ ├── turn.go # TURN 客户端(UDP/TCP/TLS
│ │ ├── turn_quic.go # TURN-QUIC 扩展
│ │ ├── stun.go # STUN 探测
│ │ ├── ice.go # ICE 协商(WebRTC
│ │ └── ws.go # WebSocket 客户端
│ ├── transport/ # 传输层
│ │ ├── conn_manager.go # Peer 连接管理器
│ │ ├── relay.go # 数据转发器(本地端口 ↔ 远端)
│ │ └── plugin.go # ProtocolPlugin 接口
│ ├── plugins/wg/ # WireGuard 插件实现
│ │ └── wgparse.go # WG 协议解析
│ ├── core.go # Core 主实例(管理多个 Engine
│ ├── engine.go # Engine 引擎(一个组网一个实例)
│ └── metrics.go # 监控指标采集
├── internal/ # 内部实现(不对外暴露)
│ ├── api/ # REST API 层
│ │ ├── handler/ # API 处理器
│ │ ├── middleware/ # 中间件(JWT 认证、CORS、日志)
│ │ ├── dto/ # 数据传输对象
│ │ ├── api.go # API 包定义
│ │ └── server.go # Gin 服务器(路由注册、静态文件服务)
│ ├── ctr/ # MeshRay-Control(调度中心)
│ │ ├── ctr.go # 调度中心主逻辑
│ │ ├── interface.go # WG 接口管理
│ │ └── wg.go # WireGuard CLI 封装
│ ├── config/ # 配置管理(Viper + 自动生成密钥)
│ │ └── config.go # Config 结构体 + Load 函数
│ ├── dnsprovider/ # DNS Provider 抽象(Cloudflare/阿里云/腾讯云)
│ ├── handler/ # 通用处理器(备份、DDNS 统计、通知、更新)
│ ├── logging/ # 日志系统(Zap 封装)
│ ├── model/ # 数据模型(GORM 定义)
│ ├── scheduler/ # 后台任务调度(DDNS 自动更新)
│ ├── service/ # 业务逻辑层
│ ├── store/ # 数据库访问层(SQLite)
│ └── tray/ # 系统托盘(Windows 交互模式)
├── pkg/ # 公共工具库(可复用)
│ ├── idutil/ # 雪花算法 ID 生成
│ ├── meshseed/ # MeshSeed 加密/签名
│ └── shortid/ # 短 ID 编码器
├── web/ # 前端静态资源
│ ├── embed.go # Go embed 定义(`//go:embed all:static`
│ └── static/ # 静态文件目录
│ ├── index.html # SPA 入口
│ └── js/app.js # 前端应用
├── config.yaml # 运行配置文件(自动生成)
├── configs/
│ └── config.example.yaml # 配置示例模板
├── deploy/ # 部署相关
│ ├── docker/ # Docker 镜像构建
│ ├── scripts/ # 安装脚本
│ └── systemd/ # Systemd 服务单元
└── docs/ # 技术文档
├── README.md # 项目介绍(本文档)
├── QUICKSTART.md # 快速入门指南
├── ARCHITECTURE.md # 架构详解
└── ...
```
**模块职责**
| 目录 | 作用 | 是否对外暴露 |
|------|------|-------------|
| **cmd/** | 可执行文件入口 | ✅ 是(编译产物) |
| **core/** | 建连层核心逻辑 | ❌ 否(内部使用) |
| **internal/** | 业务逻辑实现 | ❌ 否(Go 约定) |
| **pkg/** | 公共工具库 | ✅ 是(可复用) |
| **web/** | 前端静态资源(内嵌) | ❌ 否(构建到二进制) |
---
### 架构总览
MeshRay 采用三层架构:
```
┌─────────────────────────────────────────────┐
│ Web UI(静态 HTML/JS
└────────────────┬────────────────────────────┘
│ REST API / WebSocket
┌────────────────▼────────────────────────────┐
│ API HandlerGin 接入层) │
│ - JWT 认证中间件 │
│ - 路由注册 │
└────────────────┬────────────────────────────┘
│ 函数调用
┌────────────────▼────────────────────────────┐
│ Service Layer(业务层) │
│ - NetworkService / DeviceService │
│ - DDNSService / PolicyService │
│ - UserService / SettingsService │
│ - NotificationService / BackupService │
└────────┬──────────────────┬─────────────────┘
│ │ 函数调用(直接集成,无 gRPC)
┌────────▼──────┐ ┌──────▼─────────────────┐
│ Store Layer │ │ meshray-ctr (调度中心) │
│ (SQLite) │ │ │
│ │ │ ┌──────────────────┐ │
│ │ │ │ wgctrl 管理 WG 设备│ │
│ │ │ └──────────────────┘ │
│ │ │ │
│ │ │ ┌──────────────────┐ │
│ │ │ │ Core (建连层) │ │
│ │ │ │ Engine → 9 层策略 │ │
│ │ │ │ ConnManager + Relay│ │
│ │ │ └──────────────────┘ │
│ │ │ │
│ │ │ ┌──────────────────┐ │
│ │ │ │ Core 集成在 ctr │ │
│ │ │ │ 进程中直接调用 │ │
│ │ │ └──────────────────┘ │
│ │ │ │
│ │ │ ⚡ 直接函数调用 │
│ │ │ 无需 gRPC 通信 │
│ │ │ 无网络开销 │
│ └───┘ │
└────────────────────────────────────────────┘
```
**职责边界**
| 组件 | 做什么 | 不做什么 |
|------|--------|---------|
| **ctr** | 调度 WG 设备、控制面信令中转(通过数据库)、读写数据库 | 不碰数据面、不做建连/传输 |
| **Core** | 数据面直连、建连、策略调度、Bind 端口转发 | 不读数据库、不依赖 internal/、不管路由决策 |
| **wgctrl** | 管理 WireGuard 设备(增删 Peer、改 Endpoint) | 不负责建立连接、不处理 NAT 穿透 |
---
## 关键机制
### 1. 雪花算法 ID 生成
所有主键使用雪花算法(Snowflake)生成 uint64 ID
- **结构**1bit 符号 + 41bits 时间戳 + 10bits 节点 ID + 12bits 序列号
- **前端精度问题**:JavaScript 无法精确表示超大数字,框架层自动处理
- **实现**`pkg/idutil/snowflake.go`
### 2. Engine.Bind 模型 - 9 层传输的核心
Engine 为每个 Peer 开启一个本地 UDP 监听端口,通过 `Bind()` 方法注册到 Relay
```
WG 加密包 → Engine.Bind() 监听本地端口 → Relay 提取 Route ID → 选择链路 → 发送
Direct-UDP → FakeTCP → RealTCP → TURN-UDP → ...
```
**流程**
1. `engine.Bind(peerKey, port)` → 监听 `127.0.0.1:port`
2. `relay.RegisterLocalPort(routeID, conn)` → 注册到转发器
3. WG 将 Peer 的 Endpoint 设为 `127.0.0.1:port`(回环地址)
4. WG 发出的密文包被本地端口截获 → Relay 处理 → 策略调度器选择最优传输层发送
### 3. 9 层传输策略
```
性能好(穿透力弱) 穿透力强(兜底)
Direct-UDP → FakeTCP → RealTCP → TURN-UDP → TURN-TCP → TURN-TLS → WebRTC → WS/WSS
```
**三种使用模式**
- **自动切换**(默认):按优先级自动尝试
- **自定义策略**:用户自定义顺序
- **手动指定**:强制使用单一链路
### 4. Mesh 中继
Mesh 中继是 **WG 设备层的静态路由拓扑配置**
- ctr 通过 wgctrl 配置中继节点的 AllowedIPs
- WG 设备自身负责解密 → 路由 → 重加密 → 转发
- **Core 对中继行为完全无感知**,只负责点对点传输
**系统要求**Linux 需开启 `ip_forward=1` 和 iptables NAT
### 5. ExternalService 服务管理
统一管理所有外部依赖服务,通过 `category` + `serviceType` + JSON Config 实现:
| 服务类型 | 用途 | 示例 |
|---------|------|------|
| STUN | NAT 地址探测 | stun.l.google.com:19302 |
| TURN | 中继转发(UDP/TCP/TLS | turn.example.com:3478 |
| DDNS | 动态域名解析 | Cloudflare / 阿里云 / 腾讯云 |
| TUN | 虚拟网卡服务 | 自定义隧道 |
**数据模型**`model.Service`(轻量级统一结构,JSON Config 扩展)
---
## MeshSeed 机制
MeshSeed 是组网的统一凭证载体,一套参数同时支持:新设备加入、旧设备同步、全链路鉴权。
### 数据结构
```go
type MeshSeed struct {
NetworkName string // 组网名称
NetworkSecret string // 高熵密钥(派生 NetworkID,绝不公开)
Subnet string // CIDR 格式,如 10.0.0.0/24
IssuerNodeID string // 签发者节点 IDEd25519 公钥)
// 自动生成
SeedID string // 16 字节随机 Base64
NetworkID uint64 // 雪花算法 ID
Signature []byte // Ed25519 签名(内层签名)
IssuedAt time.Time // 签发时间
ExpiresAt time.Time // 过期时间
}
```
### 双层安全机制
| 层次 | 算法 | 作用 |
|------|------|------|
| **外层加密** | AES-256-GCM | 保证机密性(DDNS 存储时加密) |
| **内层签名** | Ed25519 | 保证完整性与来源(防篡改) |
### DDNS TXT 记录格式
```
_meshray.home.example.com. IN TXT "meshray-ddns:<base64(nonce + ciphertext)>"
```
---
## 数据模型
### 核心表
| 表名 | 说明 | 核心字段 |
|------|------|---------|
| **networks** | 组网配置 | ID, Name, Subnet, Mode, PolicyID, DDNSEnabled |
| **devices** | 设备信息 | ID, NetworkID, PublicKey, Endpoint, Status |
| **policies** | 传输策略 | ID, Name, Type, LayerConfig, GlobalParams |
| **services** | 外部服务 | ID, Name, Type, Address, Port, Config (JSON) |
| **external_services** | 统一服务注册表 | ID, Category, ServiceType, Name, Config (JSON) |
| **mesh_seeds** | 组网凭证 | SeedID, NetworkID, JoinToken, Signature |
| **users** | 用户认证 | Username, PasswordHash (bcrypt), Role |
| **ddns_providers** | DDNS 服务商配置 | Provider, Domain, AccessKey |
| **ddns_usages** | DDNS 用途定义 | UsageType, RecordType, RecordPrefix |
| **notifications** | 通知消息 | UserID, Type, Priority, Title, IsRead |
| **audit_logs** | 审计日志 | Action, OperatorIP, Detail (JSON) |
| **system_settings** | 系统设置 | ServerIP, TURNMode, Theme, Language |
| **pending_joins** | 待审核加入 | SeedID, DeviceName, Status, ExpireAt |
---
## API 概览
所有 API 通过 `http://localhost:9531/api/v1/` 访问(端口可在 `config.yaml` 中配置)。
### 认证接口
| 方法 | 路径 | 说明 |
|------|------|------|
| POST | `/api/v1/auth/login` | 登录获取 Token |
| POST | `/api/v1/auth/refresh` | 刷新 Token |
### 组网管理
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/api/v1/networks` | 组网列表 |
| POST | `/api/v1/networks` | 创建组网 |
| POST | `/api/v1/networks/preview` | 预览 MeshSeed |
| POST | `/api/v1/networks/join` | 加入组网 |
| GET | `/api/v1/networks/:id` | 组网详情 |
| PUT | `/api/v1/networks/:id` | 更新组网 |
| DELETE | `/api/v1/networks/:id` | 删除组网 |
| POST | `/api/v1/networks/:id/start` | 启动组网 |
| POST | `/api/v1/networks/:id/stop` | 停止组网 |
| POST | `/api/v1/networks/:id/switch-mode` | 切换传输模式 |
| POST | `/api/v1/networks/:id/meshseed` | 生成 MeshSeed |
### 设备管理
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/api/v1/devices` | 设备列表 |
| POST | `/api/v1/devices` | 创建设备 |
| GET | `/api/v1/devices/:id` | 设备详情 |
| PUT | `/api/v1/devices/:id` | 更新设备 |
| DELETE | `/api/v1/devices/:id` | 删除设备 |
| GET | `/api/v1/devices/:id/config` | 生成 WG 配置 |
### 策略管理
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/api/v1/policies` | 策略列表 |
| POST | `/api/v1/policies` | 创建策略 |
| GET | `/api/v1/policies/:id` | 策略详情 |
| PUT | `/api/v1/policies/:id` | 更新策略 |
| DELETE | `/api/v1/policies/:id` | 删除策略 |
### 外部服务
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/api/v1/services` | 服务列表 |
| POST | `/api/v1/services` | 新增服务 |
| GET | `/api/v1/services/:id` | 服务详情 |
| PUT | `/api/v1/services/:id` | 更新服务 |
| DELETE | `/api/v1/services/:id` | 删除服务 |
| POST | `/api/v1/services/:id/test` | 测试连通性 |
| GET | `/api/v1/services/schema` | 获取表单 Schema |
### DDNS
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/api/v1/ddns/config` | DDNS 配置 |
| PUT | `/api/v1/ddns/config` | 更新 DDNS 配置 |
| POST | `/api/v1/ddns/test` | 测试连通性 |
| POST | `/api/v1/ddns/sync` | 手动同步 |
| GET | `/api/v1/ddns/detect-ip` | IP 检测 |
| GET | `/api/v1/ddns/stats` | 统计信息 |
| POST | `/api/v1/ddns/usages` | 创建用法 |
| GET | `/api/v1/ddns/usages/available` | 可用用法列表 |
| GET | `/api/v1/ddns/check-prefix` | 检查前缀占用 |
### 系统管理
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/api/v1/admin/profile` | 管理员信息 |
| PUT | `/api/v1/admin/profile` | 更新管理员 |
| POST | `/api/v1/admin/change-password` | 修改密码 |
| GET | `/api/v1/dashboard/stats` | 仪表盘统计 |
| GET | `/api/v1/dashboard/logs` | 最近日志 |
| GET | `/api/v1/dashboard/system-info` | 系统信息 |
| GET | `/api/v1/dashboard/link-distribution` | 链路分布 |
| POST | `/api/v1/system/backup` | 创建备份 |
| GET | `/api/v1/system/backups` | 备份列表 |
| POST | `/api/v1/system/restore` | 恢复备份 |
| DELETE | `/api/v1/system/backup` | 删除备份 |
| GET | `/api/v1/system/backup/download` | 下载备份 |
| GET | `/api/v1/system/update/check` | 检查更新 |
| POST | `/api/v1/system/restart-core` | 重启核心 |
| POST | `/api/v1/system/change-password` | 修改密码 |
| GET | `/api/v1/settings` | 系统设置 |
| PUT | `/api/v1/settings` | 更新设置 |
### 通知系统
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/api/v1/notifications` | 通知列表 |
| GET | `/api/v1/notifications/unread-count` | 未读数量 |
| POST | `/api/v1/notifications/:id/read` | 标记已读 |
| POST | `/api/v1/notifications/read-all` | 全部已读 |
| DELETE | `/api/v1/notifications/:id` | 删除通知 |
| POST | `/api/v1/notifications/test` | 测试通知 |
### 待审核加入
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/api/v1/pending-joins` | 待审核列表 |
| POST | `/api/v1/pending-joins/:id/approve` | 批准 |
| POST | `/api/v1/pending-joins/:id/reject` | 拒绝 |
| GET | `/api/v1/pending-joins/count` | 待审数量 |
| POST | `/api/v1/pending-joins/cleanup` | 清理过期 |
---
## 技术栈
### 后端
| 组件 | 技术 | 版本 | 用途 |
|------|------|------|------|
| **语言** | Go | 1.21+ | 主要编程语言 |
| **Web 框架** | Gin | v1.9+ | HTTP 服务器和路由 |
| **ORM** | GORM | v2.5+ | 数据库操作 |
| **数据库** | SQLite (glebarez/go-sqlite) | v3 | 嵌入式数据库(零 CGO 依赖) |
| **日志** | Zap | v1.26+ | 结构化日志 |
| **配置** | Viper | v1.18+ | 配置管理 |
| **WireGuard** | golang.zx2c4.com/wireguard | latest | 用户态 WG 实现 |
| **DNS** | libdns | latest | 多云 DNS Provider |
| **认证** | bcrypt + golang-jwt | v5 | 密码加密 + JWT |
| **NAT 穿透** | pion/turn, pion/webrtc | latest | STUN/TURN/ICE |
### 前端
| 组件 | 技术 | 用途 |
|------|------|------|
| **UI** | 纯 JavaScript (ES6+) | 管理面板 |
| **静态资源** | Go embed (`//go:embed all:static`) | 内嵌到二进制 |
前端为纯静态 HTML/JS,无 Node.js 依赖,无需额外构建步骤。
---
## 部署方式
### 开发环境
```bash
# 编译并运行
go build -o meshray.exe ./cmd/meshray && ./meshray.exe
# 访问管理面板
http://localhost:9531
```
### 生产环境
| 方式 | 说明 |
|------|------|
| **直接运行** | 单 exe 文件部署,适合 Windows/Linux |
| **Windows 服务** | `meshray.exe install``meshray.exe start` |
| **Systemd** | 使用 `deploy/systemd/meshray.service` |
| **Docker** | 使用 `deploy/docker/docker-compose.yml` |
### 首次启动
首次启动会自动:
1. 生成 `config.yaml` 配置文件(如不存在)
2. 生成 JWT Secret 和加密密钥
3. 创建 SQLite 数据库 `data/meshray.db`
4. 创建管理员账户(用户名:`admin`,密码在控制台输出中)
---
## 版本记录
| 版本 | 核心变更 |
|------|---------|
| v2.0.0 | 初始版本 |
| v2.0.x | 重构 Core 模块,9 层传输策略实现 |
| v2.1.x | 去 gRPC 化,ctr 与 Core 直接函数调用 |
| v2.2.x | DDNS 完整功能、通知系统、备份恢复 |
| v2.3.x | 前端静态化、Embed 集成、重构完成 |
---
*MeshRay | MIT License | v2.3.x*