21 KiB
21 KiB
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 隧道 |
快速开始
# 克隆项目
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 Handler(Gin 接入层) │
│ - 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 → ...
流程:
engine.Bind(peerKey, port)→ 监听127.0.0.1:portrelay.RegisterLocalPort(routeID, conn)→ 注册到转发器- WG 将 Peer 的 Endpoint 设为
127.0.0.1:port(回环地址) - 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 是组网的统一凭证载体,一套参数同时支持:新设备加入、旧设备同步、全链路鉴权。
数据结构
type MeshSeed struct {
NetworkName string // 组网名称
NetworkSecret string // 高熵密钥(派生 NetworkID,绝不公开)
Subnet string // CIDR 格式,如 10.0.0.0/24
IssuerNodeID string // 签发者节点 ID(Ed25519 公钥)
// 自动生成
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 依赖,无需额外构建步骤。
部署方式
开发环境
# 编译并运行
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 |
首次启动
首次启动会自动:
- 生成
config.yaml配置文件(如不存在) - 生成 JWT Secret 和加密密钥
- 创建 SQLite 数据库
data/meshray.db - 创建管理员账户(用户名:
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