8.7 KiB
Xboard 对接 V2bX 完整文档
本文基于以下两套源码交叉整理:
- 面板端:
Xboard-new - 节点端:
E:/code/go/V2bX
适用目标:让 V2bX 节点稳定对接 Xboard,完成配置拉取、用户同步、流量上报、在线设备上报。
1. 对接结论(先看这个)
V2bX当前固定请求Xboard的V1 UniProxy路径(不是V2路径):GET /api/v1/server/UniProxy/configGET /api/v1/server/UniProxy/userGET /api/v1/server/UniProxy/alivelistPOST /api/v1/server/UniProxy/pushPOST /api/v1/server/UniProxy/alive
- 鉴权依赖 URL Query 参数:
token、node_id、node_type。 Xboard的server_token长度需要 >= 16。V2bX启动时如果拉不到可用用户会直接报错退出:add users error: not have any user。- 在线设备数据写入由队列任务处理,面板端必须保证队列消费者(通常
horizon)在运行。
2. 源码级接口对齐
2.1 V2bX 侧(请求方)
关键实现:
api/panel/panel.go:初始化 Query 参数(node_type/node_id/token),并限制NodeType枚举。api/panel/node.go:拉取节点配置(/api/v1/server/UniProxy/config)。api/panel/user.go:拉取用户、在线列表,上报流量和在线 IP。node/controller.go:启动时先拉配置和用户,再注册节点。node/task.go:按pull_interval/push_interval定时同步与上报。
2.2 Xboard 侧(服务方)
关键实现:
app/Http/Routes/V1/ServerRoute.php:/api/v1/server/UniProxy/*路由定义。app/Http/Middleware/Server.php:校验token/node_id/node_type,并注入node_info。app/Http/Controllers/V1/Server/UniProxyController.php:实现config/user/push/alive/alivelist/status。app/Services/ServerService.php:按node_id(支持code或id)和node_type查节点,按权限组取可用用户。app/Jobs/UpdateAliveDataJob.php:异步写在线设备计数。
3. 类型与协议兼容要点
V2bX 允许的 NodeType(api/panel/panel.go):
vmessvlesstrojanshadowsockshysteriahysteria2tuicanytls- 兼容别名:
v2ray -> vmess
Xboard 节点类型(app/Models/Server.php)有别名:
v2ray -> vmesshysteria2 -> hysteria
建议:
- 绝大多数场景按面板节点真实类型填写
NodeType。 - Hysteria v2 场景建议仍使用
NodeType: "hysteria",在面板协议设置里把version设为2,避免类型语义混乱。 V2bX并不对接Xboard的socks/naive/http/mieru这几类。
4. Xboard 面板端配置步骤
4.1 全局通信参数
后台系统配置里设置:
server_token:与 V2bX 的ApiKey完全一致,长度建议 32+。server_pull_interval:节点拉配置周期(秒)。server_push_interval:节点推送流量周期(秒)。device_limit_mode:设备限制统计策略(按你的业务选)。
源码依据:
app/Http/Controllers/V2/Admin/ConfigController.phpapp/Http/Requests/Admin/ConfigSave.php
4.2 创建节点(每个 NodeID 对应一个节点)
至少需要正确配置:
typenamehostportserver_portgroup_idsrateprotocol_settings(按协议必填项)
源码依据:app/Http/Requests/Admin/ServerSave.php
4.3 用户可用性条件(非常关键)
节点可拉到的用户必须同时满足(ServerService::getAvailableUsers):
- 用户
group_id在节点group_ids内 u + d < transfer_enable- 未过期
- 未被禁用
否则 V2bX 首次启动可能直接失败(无可用用户)。
4.4 队列进程
/alive 上报会派发 UpdateAliveDataJob 到 online_sync 队列。
若没有队列消费者,在线设备统计会滞后或不更新。
建议至少保证:
php artisan horizon正常运行
5. V2bX 配置(可直接改)
参考 E:/code/go/V2bX/example/config.json。
5.1 单节点最小可用示例
{
"Log": {
"Level": "info",
"Output": ""
},
"Cores": [
{
"Type": "sing",
"Log": {
"Level": "info",
"Timestamp": true
},
"OriginalPath": "/etc/V2bX/sing_origin.json"
}
],
"Nodes": [
{
"Core": "sing",
"ApiHost": "https://panel.example.com",
"ApiKey": "请填写与Xboard一致的server_token",
"NodeID": 1,
"NodeType": "vmess",
"Timeout": 30,
"ListenIP": "0.0.0.0",
"SendIP": "0.0.0.0",
"DeviceOnlineMinTraffic": 200,
"MinReportTraffic": 0
}
]
}
5.2 字段说明(高频踩坑项)
ApiHost:必须是面板根地址,不要写成.../api/v1。ApiKey:对应Xboard server_token。NodeID:对应面板节点id(或数值型code)。NodeType:必须是 V2bX 支持的枚举。Timeout:HTTP 超时秒数。ApiSendIP(可选):多网卡时指定请求源 IP。
源码依据:E:/code/go/V2bX/conf/node.go
6. 启动与热重载
6.1 启动命令
V2bX server -c /etc/V2bX/config.json
默认支持 --watch(开启配置监听),配置文件变化后会自动重载核心和节点。
源码依据:E:/code/go/V2bX/cmd/server.go
6.2 建议运行形态
- 使用
systemd托管V2bX - 配置
Restart=always - 单独落日志文件,便于排错
7. 联调验证(建议按顺序)
7.1 手工验证面板接口可达
在节点机执行(把参数换成你的真实值):
curl -sS "https://panel.example.com/api/v1/server/UniProxy/config?node_type=vmess&node_id=1&token=YOUR_TOKEN"
预期:返回 JSON,包含 base_config.push_interval 与 base_config.pull_interval。
curl -sS "https://panel.example.com/api/v1/server/UniProxy/user?node_type=vmess&node_id=1&token=YOUR_TOKEN"
预期:返回 users 列表,且非空(至少有一个可用用户)。
7.2 启动后看 V2bX 日志
应出现这类信息:
Core ... startedNodes started- 周期性
Report N users traffic - 周期性在线用户上报日志
7.3 面板侧确认
- 节点状态
last_check_at、last_push_at持续刷新 - 用户流量持续累加
online_count有变化(需要队列正常)
8. 常见问题与处理
8.1 unsupported Node type
原因:NodeType 不在 V2bX 白名单。
处理:改为支持值(如 vmess/vless/trojan/shadowsocks/hysteria/tuic/anytls)。
8.2 Invalid token
原因:ApiKey != server_token。
处理:面板与节点统一同一密钥,并确认没有前后空格。
8.3 Server does not exist
原因:
NodeID错误NodeType与面板节点类型不匹配
处理:先在面板确认节点 ID/类型,再校正 V2bX 配置。
8.4 add users error: not have any user
原因:该节点按权限组筛选后没有可用用户。
处理:
- 确认节点
group_ids - 确认至少一个用户满足流量/到期/禁用条件
8.5 在线设备不上报或不更新
原因:面板队列消费者未运行。
处理:启动并确认 horizon 正常消费(尤其 online_sync 队列)。
8.6 配置路径重复导致 404
原因:ApiHost 写成 https://panel/api/v1,最终拼接成重复路径。
处理:ApiHost 只保留根域名(如 https://panel.example.com)。
9. 请求/响应数据形状(排错用)
9.1 配置拉取
- 请求:
GET /api/v1/server/UniProxy/config?node_type=...&node_id=...&token=... - 响应:按协议字段 +
base_config
9.2 用户拉取
- 请求:
GET /api/v1/server/UniProxy/user?... - 响应:
{"users":[{"id":1,"uuid":"...","speed_limit":0,"device_limit":0}]}(也兼容 msgpack)
9.3 流量上报
- 请求:
POST /api/v1/server/UniProxy/push?... - Body(V2bX 实际发送):
{
"1001": [12345, 67890],
"1002": [11111, 22222]
}
9.4 在线上报
- 请求:
POST /api/v1/server/UniProxy/alive?... - Body:
{
"1001": ["1.1.1.1", "2.2.2.2"],
"1002": ["3.3.3.3"]
}
10. 安全建议
ApiHost必须用 HTTPS。server_token使用高强度随机值并定期轮换。- 在反向代理/Nginx 层限制节点来源 IP 访问
server/UniProxy接口。 - 变更
server_token后,面板与全部节点必须同时切换。
11. 代码参考索引
Xboard:
app/Http/Routes/V1/ServerRoute.phpapp/Http/Middleware/Server.phpapp/Http/Controllers/V1/Server/UniProxyController.phpapp/Services/ServerService.phpapp/Jobs/UpdateAliveDataJob.phpapp/Http/Requests/Admin/ConfigSave.phpapp/Http/Requests/Admin/ServerSave.php
V2bX:
api/panel/panel.goapi/panel/node.goapi/panel/user.gonode/controller.gonode/task.gonode/user.goconf/node.gocmd/server.goexample/config.json