12 KiB
12 KiB
MeshRay-Core 架构规范
Core 是通用的数据传输引擎,通过 ProtocolPlugin 接口适配不同协议。当前默认内置 WG 插件。
一、目录结构
core/
├── core.go # 进程入口
├── engine.go # 引擎实例
├── metrics.go # 监控指标
│
├── connect/ # 建连层
│ ├── strategy.go # 策略调度
│ ├── stun.go # STUN 协议
│ ├── direct.go # Layer 1
│ ├── fake_tcp.go # Layer 2
│ ├── real_tcp.go # Layer 3
│ ├── turn.go # Layer 4/6/7
│ ├── turn_quic.go # Layer 5
│ ├── ice.go # Layer 8
│ └── ws.go # Layer 9
│
├── transport/ # 传输层
│ ├── conn_manager.go # 连接索引
│ ├── relay.go # 转发循环
│ └── plugin.go # Plugin 接口
│
└── plugins/ # 协议插件
└── wg/
└── wgparse.go # WG 插件实现
二、各文件职责
2.1 根目录(4 个文件)
| 文件 | 职责 | 持有什么 | 不做什么 |
|---|---|---|---|
core.go |
进程入口,管理多个 Engine | map[engineID]*Engine |
不做建连、不转发数据 |
engine.go |
一个组网的引擎实例 | strategy、conn_manager、relay、plugin | 不直接调用 connect,由 relay 调用 |
metrics.go |
监控指标采集 | 原子计数器(连接数、字节数、切换次数) | 不做业务逻辑 |
关键关系:
core.go持有多个engine.gointernal/ctr/ctr.go直接调用core.go和engine.go(进程内函数调用)engine.go持有 connect/、transport/、plugins/ 的实例
2.2 connect/(9 个文件)— 建连层
职责:通过各种网络方式建立连接,最终返回 net.Conn。
对外暴露的唯一入口:strategy.go 的 Connect() 方法。其他 connect 文件只被 strategy.go 调用。
| 文件 | 对应层级 | 职责 | 返回什么 |
|---|---|---|---|
strategy.go |
全部 | 按优先级尝试各层,不通自动切换,定期探测恢复 | net.Conn + 当前层级名 |
stun.go |
被 direct/ice 调用 | STUN 协议:发送 Binding Request,获取本机公网地址 | *net.UDPAddr(地址,不是连接) |
direct.go |
Layer 1 | 调用 stun 获取候选地址,然后 UDP 打洞 | net.Conn |
fake_tcp.go |
Layer 2 | UDP 包外层封装 TCP 头部,欺骗防火墙 | net.Conn |
real_tcp.go |
Layer 3 | 真正的 TCP 直连打洞 | net.Conn |
turn.go |
Layer 4/6/7 | TURN 协议协商(Allocate/Permission/ChannelBind),参数区分 UDP/TCP/TLS | net.Conn |
turn_quic.go |
Layer 5 | TURN-QUIC 私有扩展(RFC 9000) | net.Conn |
ice.go |
Layer 8 | ICE 协商 + WebRTC DataChannel,内部调用 stun 收集候选 | net.Conn |
ws.go |
Layer 9 | WS/WSS 握手 + 帧收发 + 身份标识 | net.Conn |
9 层完整编号:
| 层级 | 链路名称 | 文件 | 传输方式 | 穿透力 |
|---|---|---|---|---|
| 1 | Direct-UDP | direct.go | P2P 直连 | 弱(性能最好) |
| 2 | Direct-FakeTCP | fake_tcp.go | P2P 直连 | 弱 |
| 3 | Direct-RealTCP | real_tcp.go | P2P 直连 | 中 |
| 4 | TURN-UDP | turn.go | 中继 | 中 |
| 5 | TURN-QUIC | turn_quic.go | 中继 | 中 |
| 6 | TURN-TCP | turn.go | 中继 | 强 |
| 7 | TURN-TLS | turn.go | 中继 | 强 |
| 8 | WebRTC | ice.go | ICE/TURN | 强 |
| 9 | WS/WSS | ws.go | 隧道 | 最强(兜底) |
strategy.go 的自动切换逻辑:
- 单包超时 500ms → 切到下一层
- 10s 滑动窗口丢包率 > 10% → 切到下一层
- 当前在第 N 层时,每 30s 探测 Layer 1 → 连续 2 次成功直接切回 Layer 1(不逐层回退)
stun.go 的特殊地位:唯一被多处调用的 connect 文件(direct.go 和 ice.go 都需要它),所以独立存在。
2.3 transport/(3 个文件)— 传输层
职责:用 net.Conn 转发数据。不感知具体协议,通过 ProtocolPlugin 接口适配。
| 文件 | 职责 | 不做什么 |
|---|---|---|
conn_manager.go |
连接索引:peer_key → net.Conn 的映射 |
不做建连、不转发数据 |
relay.go |
Read/Write 循环:从本地端口收包 → 查路由 → 通过 conn 发送;从 conn 收包 → 发到本地端口 | 不做建连 |
plugin.go |
定义 ProtocolPlugin 接口 | 不实现任何协议 |
relay.go 的工作流程:
本地端口收到 WG 密文包
→ 调用 plugin.IsControlPacket() 判断包类型
→ true:控制包,按已建链路透传
→ 调用 plugin.IsDataPacket() 判断
→ true:调用 plugin.ExtractRouteID() 提取路由标识
→ 查路由标识映射表 → 发往对应本地端口
→ 都不是:丢弃
关键:relay.go 不知道 WireGuard,不知道 receiver index,只知道 route_id。
2.4 plugins/wg/(1 个文件)— 协议插件
职责:实现 ProtocolPlugin 接口,处理 WG 协议特有的包解析。
| 文件 | 职责 | 不做什么 |
|---|---|---|
wgparse.go |
实现 IsDataPacket/ExtractRouteID/IsControlPacket |
不做建连、不转发数据 |
WG 插件的具体实现:
| 方法 | 逻辑 |
|---|---|
IsControlPacket(packet) |
packet[0] ∈ {1, 2, 3} → true |
IsDataPacket(packet) |
packet[0] == 4 → true |
ExtractRouteID(packet) |
读取 packet[4:8],网络字节序解析为 uint32(即 WG receiver index) |
2.5 plugins/wg/(1 个文件)
| 文件 | 职责 |
|---|---|
wgparse.go |
WireGuard 数据包解析和封装 |
三、分层架构图
┌─────────────────────────────────────────────────────────┐
│ internal/ctr/ctr.go │
│ 直接调用 Core (进程内函数调用) │
└────────────────────────┬────────────────────────────────┘
│ 函数调用
┌────────────────────────▼────────────────────────────────┐
│ core.go │
│ 管理多个 Engine 实例 │
└───┬─────────────────────────────────────────────────────┘
│ 每个组网一个 Engine
▼
┌─────────────────────────────────────────────────────────┐
│ engine.go │
│ 持有:strategy + conn_manager + relay + plugin │
│ 协调 connect/ 和 transport/ 工作 │
└───┬─────────────────────────────────────────────────────┘
│
├──────────────────────────────────────────┐
▼ ▼
┌───────────────────────┐ ┌───────────────────────┐
│ connect/ │ │ transport/ │
│ 建连层 │ │ 传输层 │
│ │ │ │
│ strategy.go │ 返回 │ relay.go │
│ ├─ direct.go (L1) │ net.Conn├─ plugin.go │
│ ├─ fake_tcp.go (L2) │────────►│ │ ProtocolPlugin │
│ ├─ real_tcp.go (L3) │ │ │ │
│ ├─ turn.go (L4/6/7) │ │ 插件调用 │
│ ├─ turn_quic.go(L5) │ │ ▼ │
│ ├─ ice.go (L8) │ │ plugins/wg/ │
│ └─ ws.go (L9) │ │ └─ wgparse.go │
│ │ │ │
│ stun.go (被 direct/ice 调用) │ conn_manager.go │
└───────────────────────┘ └───────────────────────┘
四、调用关系
4.1 Engine 创建时
engine.go
→ 创建 WGPlugin(plugins/wg/wgparse.go)
→ 创建 Relay,传入 plugin(transport/relay.go)
→ 创建 Strategy(connect/strategy.go)
→ 创建 ConnManager(transport/conn_manager.go)
4.2 Bind 流程
ctr 直接调用:Bind()
→ engine.go 接收函数调用
→ engine.go 调用 strategy.Connect()
→ strategy 按优先级尝试各层
→ Layer 1: direct.go 调用 stun.go 获取候选,尝试 UDP 打洞
→ 不通?→ Layer 4: turn.go 调用 TURN 协商
→ 不通?→ Layer 9: ws.go 调用 WS 握手
→ 返回 net.Conn + 当前层级名
→ engine.go 把 net.Conn 注册到 conn_manager
→ engine.go 启动 relay 的 Read/Write 循环
4.3 数据转发流程
WG 发出密文包 → 本地端口
→ relay.go 收到
→ 调用 plugin.IsControlPacket()
→ true:按已建链路透传(conn_manager 查 conn)
→ 调用 plugin.IsDataPacket()
→ true:调用 plugin.ExtractRouteID() 获取 route_id
→ 查路由标识映射表 → 找到本地端口 → 发送
→ 都不是:丢弃
五、通用层与插件层的边界
| 层 | 知道什么 | 不知道什么 |
|---|---|---|
| connect/ | 网络协议(STUN/TURN/WS/WebRTC) | WireGuard、route_id |
| transport/ | net.Conn、route_id、ProtocolPlugin 接口 | WireGuard、receiver index |
| plugins/wg/ | WG 包格式、receiver index | 网络连接、net.Conn |
| engine.go | 协调 connect/ 和 transport/ | WG 包格式细节 |
如果将来要支持其他协议:
- 新建
plugins/xxx/xxxparse.go - 实现
ProtocolPlugin接口的三个方法 engine.go里换成xxx.NewPlugin()- connect/、transport/、core.go 的代码完全不用改
六、Core 接口(直接被 ctr 调用)
| 方法 | 调用方 | 说明 |
|---|---|---|
CreateEngine |
ctr | 创建一个 Engine 实例(直接函数调用) |
Bind |
ctr | 为每个 Peer 开启本地端口,开始建链 |
Unbind |
ctr | 停止指定 Peer 的端口监听 |
Start |
ctr | 启动转发主循环 |
Stop |
ctr | 停止 Engine |
GetStatus |
ctr | 查询 Engine 状态 |
NotifyPeerInfo |
ctr | 下发对端候选地址和 route_id |
实现位置:
- 所有方法都在
engine.go中实现 core.go提供 Engine 实例管理- ctr通过
coreInst.CreateEngine(...)直接调用
七、文件清单汇总
| 目录 | 文件数 | 文件 |
|---|---|---|
| 根目录 | 3 | core.go, engine.go, metrics.go |
| connect/ | 9 | strategy.go, stun.go, direct.go, fake_tcp.go, real_tcp.go, turn.go, turn_quic.go, ice.go, ws.go |
| transport/ | 3 | conn_manager.go, relay.go, plugin.go |
| plugins/wg/ | 1 | wgparse.go |
| 总计 | 16 |
已删除的文件:
grpc_service.go- 不再需要(改为直接函数调用)pool/connpool.go- 不再需要(无连接池)proto/core.proto- 不再需要 gRPC