Files
mmw-agent/README.md
T
2026-04-27 16:33:04 +08:00

13 KiB
Raw Blame History

mmw-agent

妙妙屋X 远程服务器代理程序。部署在子服务器上,负责与主控(miaomiaowux)通信,上报流量/速度数据,并接受主控的远程管理指令。

架构

┌─────────────────────────────────────────────────────┐
│                    Master (miaomiaowux)              │
│                                                     │
│  /api/remote/ws        WebSocket 双向通信            │
│  /api/remote/traffic   HTTP 流量推送                 │
│  /api/remote/speed     HTTP 速度推送                 │
│  /api/remote/heartbeat HTTP 心跳                    │
└──────────────────────┬──────────────────────────────┘
                       │
          ┌────────────┼────────────┐
          │ WebSocket  │ HTTP Push  │ Pull (被动)
          └────────────┼────────────┘
                       │
┌──────────────────────▼──────────────────────────────┐
│                    mmw-agent                         │
│                                                     │
│  内部组件:                                           │
│  ├── Agent Client    连接管理 + 数据上报              │
│  ├── Collector       Xray 流量采集 (/debug/vars)     │
│  ├── Handler         本地管理 API (/api/child/*)     │
│  └── xRPC            Xray gRPC 管理                  │
│                                                     │
│  监听端口: :23889 (管理API)                          │
│  Xray metrics: :38889 (/debug/vars)                 │
└─────────────────────────────────────────────────────┘

构建与运行

# 构建
go build -ldflags="-s -w" -o mmw-agent ./cmd/mmw-agent

# 运行(配置文件方式)
./mmw-agent -c config.yaml

# 运行(环境变量方式)
MMWX_MASTER_URL=https://master.example.com \
MMWX_MASTER_TOKEN=your-token \
./mmw-agent

配置

配置文件 (YAML)

master_server: "https://master.example.com"
remote_token: "your-server-token"
connection_mode: "auto"          # auto | websocket | http | pull
listen_port: 23889
child_api_token: ""              # 可选,pull模式API认证
traffic_report_interval: 60      # 秒
speed_report_interval: 3         # 秒
heartbeat_interval: 30           # 秒
xray_servers:                    # 可选,不配则自动发现
  - config_path: "/usr/local/etc/xray/config.json"

环境变量

变量 说明 默认值
MMWX_MASTER_URL 主控地址
MMWX_MASTER_TOKEN 服务器令牌
MMWX_CONNECTION_MODE 连接模式 auto
MMWX_LISTEN_PORT 监听端口 23889
MMWX_CHILD_API_TOKEN Pull API 认证令牌
MMWX_TRAFFIC_INTERVAL 流量上报间隔(秒) 60
MMWX_SPEED_INTERVAL 速度上报间隔(秒) 3
MMWX_HEARTBEAT_INTERVAL 心跳间隔(秒) 30

环境变量优先级高于配置文件。

Xray 自动发现

未显式配置 xray_servers 时,agent 按以下路径搜索 Xray 配置:

  1. /usr/local/etc/xray/config.json
  2. /etc/xray/config.json
  3. /opt/xray/config.json

连接模式

Auto(推荐)

自动回退链:WebSocket → HTTP → Pull,带指数退避重连。

尝试 WebSocket 连接
  ├── 成功 → 保持 WebSocket 双向通信
  │         断开后退避重连,期间通过 HTTP 发送流量保持在线
  └── 失败 → 尝试 HTTP 推送
                ├── 成功 → 定时 HTTP POST 上报
                │         连续 5 次失败后重试上层
                └── 失败 → 回退 Pull 模式
                              等待退避时间后重试上层

退避策略:基础 5s,指数增长,上限 5min。

WebSocket

全双向通信。支持:

  • Agent → Master:流量、速度、心跳、证书结果、扫描结果、域延迟探测结果
  • Master → Agent:证书请求、证书部署、令牌更新、域延迟探测

连续 5 次连接失败后自动切换到 Auto 模式回退。

HTTP

单向推送。Agent 定时 POST 数据到 Master

  • /api/remote/traffic — 流量数据
  • /api/remote/speed — 速度数据
  • /api/remote/heartbeat — 心跳

Pull

被动模式。Agent 仅暴露本地 API,等待 Master 主动拉取:

  • GET /api/child/traffic
  • GET /api/child/speed

认证机制

所有请求必须同时满足:

  1. User-Agent: miaomiaowux/0.1
  2. Authorization: Bearer <token>(或 X-Remote-Token header

未通过认证的连接被静默丢弃(TCP hijack 后直接关闭,不返回 HTTP 响应)。


API 文档

健康检查(无需认证)

方法 路径 说明
GET /health 健康检查

本地管理 API (/api/child/*)

以下所有端点均需通过 Silent Auth 中间件认证。

服务管理

方法 路径 说明
GET /api/child/services/status 获取 Xray/Nginx 服务运行状态
POST /api/child/services/control 控制服务启停
// POST /api/child/services/control
{ "service": "xray", "action": "restart" }
// service: xray | nginx
// action: start | stop | restart

Xray 管理

方法 路径 说明
POST /api/child/xray/install 安装 XraySSE 流式输出)
POST /api/child/xray/remove 卸载 XraySSE 流式输出)
GET /api/child/xray/config 获取 Xray 完整配置
PUT /api/child/xray/config 写入 Xray 完整配置
GET /api/child/xray/config/files 列出 Xray 配置文件
GET /api/child/xray/system-config 获取 Xray 系统配置路径信息

Nginx 管理

方法 路径 说明
POST /api/child/nginx/install 安装 NginxSSE 流式输出)
POST /api/child/nginx/remove 卸载 NginxSSE 流式输出)
GET /api/child/nginx/config 获取 Nginx 配置
PUT /api/child/nginx/config 写入 Nginx 配置
GET /api/child/nginx/config/files 列出 Nginx 配置文件

Xray 入站/出站/路由 (gRPC)

方法 路径 说明
GET /api/child/inbounds 列出所有入站
POST /api/child/inbounds 添加入站
PUT /api/child/inbounds 更新入站
DELETE /api/child/inbounds 删除入站(query: ?tag=xxx
GET /api/child/outbounds 列出所有出站
POST /api/child/outbounds 添加出站
PUT /api/child/outbounds 更新出站
DELETE /api/child/outbounds 删除出站(query: ?tag=xxx
GET /api/child/routing 获取路由规则
PUT /api/child/routing 更新路由规则

请求体为标准 Xray JSON 配置对象。

扫描与探测

方法 路径 说明
POST /api/child/scan 扫描 Xray 运行状态与入站配置
POST /api/child/domains/latency 域名延迟探测(TCP
// POST /api/child/domains/latency
{
  "domains": ["example.com", "test.org"],
  "timeout_ms": 5000
}
// 并发 TCP 探测,自动去重,最多 200 个域名

扫描自动补全/api/child/scan 会检查 Xray 配置完整性,自动补全缺失的 apistatspolicy 段及 API 入站和路由规则,补全后自动重启 Xray。

系统信息

方法 路径 说明
GET /api/child/system/info 获取系统信息(OS、CPU、内存、磁盘)

Pull 模式数据接口

方法 路径 说明
GET /api/child/traffic 获取当前 Xray 流量统计
GET /api/child/speed 获取当前系统网络速度
// GET /api/child/traffic 响应
{
  "stats": {
    "inbound":  { "tag": { "uplink": 1024, "downlink": 2048 } },
    "outbound": { "tag": { "uplink": 512,  "downlink": 1024 } },
    "user":     { "email": { "uplink": 256, "downlink": 512 } }
  }
}

// GET /api/child/speed 响应
{
  "upload_speed": 102400,
  "download_speed": 204800
}
// 单位:字节/秒 (B/s),来源:/proc/net/dev 物理网卡聚合

WebSocket 交互协议

连接地址:ws(s)://<master>/api/remote/ws

消息格式

所有消息为 JSON,统一结构:

{
  "type": "<message_type>",
  "payload": { ... }
}

连接流程

Agent                                    Master
  │                                        │
  │──── WebSocket Connect ────────────────>│
  │     Header: User-Agent: miaomiaowux/0.1
  │                                        │
  │──── auth ─────────────────────────────>│
  │     { "token": "server-token" }        │
  │                                        │
  │<─── auth_result ──────────────────────│
  │     { "success": true }                │
  │                                        │
  │──── traffic (定时) ───────────────────>│
  │──── speed (定时) ─────────────────────>│
  │──── heartbeat (定时) ─────────────────>│
  │                                        │
  │<─── cert_request ─────────────────────│
  │──── cert_update ──────────────────────>│
  │                                        │
  │<─── cert_deploy ──────────────────────│
  │<─── token_update ─────────────────────│
  │<─── domain_latency_probe ─────────────│
  │──── domain_latency_result ────────────>│
  │                                        │
  │──── scan_result (首次连接) ───────────>│

消息类型

Agent → Master

type 说明 payload
auth 认证 { "token": "string" }
traffic 流量数据 { "stats": { "inbound": {}, "outbound": {}, "user": {} } }
speed 实时速度 { "upload_speed": int64, "download_speed": int64 }
heartbeat 心跳 { "boot_time": "RFC3339" }
cert_update 证书申请结果 { "cert_id": int, "domain": "string", "success": bool, "cert_pem": "string", "key_pem": "string", "issue_date": "time", "expiry_date": "time", "error": "string" }
scan_result Xray 扫描结果 { "xray_running": bool, "xray_version": "string", "inbounds": [...] }
domain_latency_result 域延迟探测结果 { "request_id": "string", "success": bool, "results": [{ "domain": "string", "latency_ms": int64, "success": bool }] }

Master → Agent

type 说明 payload
auth_result 认证结果 { "success": bool, "message": "string" }
cert_request 请求申请证书 { "cert_id": int, "domain": "string", "email": "string", "provider": "string", "challenge_mode": "string", ... }
cert_deploy 部署证书文件 { "domain": "string", "cert_pem": "string", "key_pem": "string", "cert_path": "string", "key_path": "string", "reload": "nginx|xray|both|none" }
token_update 推送新令牌 { "server_token": "string", "expires_at": "RFC3339" }
domain_latency_probe 域延迟探测请求 { "request_id": "string", "domains": ["string"], "timeout_ms": int }

认证流程

  1. Agent 建立 WebSocket 连接(必须携带 User-Agent: miaomiaowux/0.1
  2. Agent 发送 auth 消息,携带服务器令牌
  3. Master 验证令牌,返回 auth_result
  4. 认证成功后进入消息循环;未认证的消息会收到 auth_result { success: false, message: "Authentication required" }

令牌轮换

Master 可通过 token_update 推送新令牌。Agent 收到后:

  1. 将新令牌持久化到本地配置
  2. 后续所有请求使用新令牌
  3. Master 端同步更新连接映射

首次连接自动扫描

Agent 认证成功后自动执行 Xray 扫描,将结果通过 scan_result 发送给 Master。如果服务器处于 pending 状态且配置了域名和 443 端口,Master 会自动触发 steal-self 配置部署。


数据采集

流量采集

从 Xray 的 /debug/vars HTTP 端点采集,解析 stats 对象中的 inbound/outbound/user 流量数据。

metrics 地址从 Xray 配置文件的 api 段中的 listen 字段获取,默认 127.0.0.1:38889

速度采集

读取 /proc/net/dev,聚合所有物理网卡(排除 lo)的收发字节数,计算两次采样间的速率差值。

上传速度 = (当前 TX - 上次 TX) / 采样间隔
下载速度 = (当前 RX - 上次 RX) / 采样间隔