docs: improve deployment and agent guides

This commit is contained in:
JetSprow
2026-04-29 19:55:09 +10:00
parent 843753bed6
commit 7269afa9bb
4 changed files with 916 additions and 278 deletions

View File

@@ -3,3 +3,56 @@
This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` before writing any code. Heed deprecation notices. This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` before writing any code. Heed deprecation notices.
<!-- END:nextjs-agent-rules --> <!-- END:nextjs-agent-rules -->
# Repository Notes For Coding Agents
This file is for agents working in this repository. Product, deployment, API, and operations documentation belongs in `README.md`, `docs/API.md`, and `agent/jboard-agent/README.md`.
## Project Shape
J-Board is a Next.js App Router application backed by Prisma/PostgreSQL and Redis. It integrates with 3x-ui rather than replacing it:
- J-Board owns users, orders, plans, subscriptions, payments, support, notifications, audit logs, settings, and risk review.
- 3x-ui owns actual inbound runtime configuration and Xray clients.
- `agent/jboard-agent` is a read-only sidecar for latency, route trace, and optional Xray access log telemetry.
Do not add a new node control plane or Xray process manager unless the user explicitly changes the product direction.
## Next.js Work
Before editing App Router files, route handlers, server actions, metadata, or caching behavior, read the relevant docs from `node_modules/next/dist/docs/` for the installed Next.js version.
Common areas to check:
- App Router file conventions.
- Route Handler request/response behavior.
- Server Actions and `use server` requirements.
- Caching, `revalidatePath`, and dynamic rendering rules.
## Version And Release Policy
Panel and Agent versions are not forced to move together.
- Website/admin/UI/docs/server-only changes can be committed and pushed to `main` without creating a GitHub Release.
- Only create a new Agent tag and GitHub Release when Agent code, Agent install/upgrade behavior, or Agent release artifacts change.
- Agent releases must include `jboard-agent-linux-amd64`, `jboard-agent-linux-arm64`, and `SHA256SUMS`.
- Agent runtime version is in `agent/jboard-agent/cmd/agent/main.go`.
- Agent build version is in `agent/jboard-agent/Makefile`.
- Panel package version is in `package.json` and does not need to match the Agent version.
## Documentation Policy
When changing behavior, update docs in the same change:
- User/deployment/admin docs: `README.md`.
- HTTP API and Server Actions: `docs/API.md` and, for public HTTP changes, `docs/openapi.yaml`.
- Agent install, runtime, logs, and release behavior: `agent/jboard-agent/README.md`.
- Agent-facing repository rules: this file.
Keep docs factual and operational. Avoid promising features that are not implemented.
## Risk And Privacy Notes
Subscription risk and node access telemetry contain sensitive evidence: user IPs, locations, Xray client email, target hosts, timestamps, and admin review decisions. Treat these as sensitive data in logs, docs, screenshots, and tests.
Agent Xray log telemetry must remain read-only. It may read access logs and post aggregates to J-Board; it must not mutate 3x-ui or Xray runtime configuration.

525
README.md
View File

@@ -1,176 +1,156 @@
# J-Board # J-Board
J-Board也称 JB面板是一个面向代理订阅售卖与流媒体共享的全栈应用。节点运行、入站和客户端配置由 3x-ui 面板维护J-Board 负责售卖、订单、订阅、用户、支付、工单和探测展示;自带 Go 程序只做延迟与线路探测上报 J-Board也称 JB 面板)是一个面向代理订阅售卖与流媒体共享的全栈管理面板。它负责用户、套餐、订单、支付、订阅、工单、邮件、公告、审计、探测展示与订阅风控节点实际运行、入站协议、Xray 客户端配置由 3x-ui 维护
## 架构 J-Board 的定位很明确:它不是新的节点控制面,也不替代 3x-ui。它把售卖、开通、订阅交付、售后和风险审查做成一个完整面板并通过只读 Agent 从节点侧采集延迟、路由和 Xray access log 证据。
## 快速认识
```text ```text
用户浏览器 用户浏览器 / 客户端订阅
Next.js App Router 面板 Next.js App Router 面板
├─ PostgreSQL / Redis ├─ PostgreSQL:用户、订单、套餐、订阅、审计、风控事件
├─ 3x-ui API同步入站、开通/暂停/删除客户端 ├─ Redis限流、后台任务与缓存辅助
Probe API接收 jboard-agent 的延迟与路由上报 3x-ui API同步入站、开通/暂停/删除代理客户端
└─ Agent API接收 jboard-agent 上报的延迟、路由、节点真实连接日志
节点 VPS
├─ 3x-ui / Xray真实入站、客户端、流量限制与代理运行
└─ jboard-agent旁路只读探测与日志聚合不修改 3x-ui 配置
``` ```
J-Board 只保存售卖和展示需的节点、入站、客户端镜像数据,不下发 Xray/Hy2 配置,也不维护自建节点控制面 J-Board 只保存售卖和展示需的节点镜像数据。入站协议、端口、Reality/TLS、Xray 运行状态和客户端真实配置仍以 3x-ui 为准
## 功能 ## 功能概览
用户端: 用户端:
- 注册、登录、Cloudflare Turnstile 人机验证 - 注册、登录、邮箱验证、忘记密码、邮箱变更验证
- 代理套餐与流媒体套餐购买、续费、增流量 - 支持 Cloudflare Turnstile 人机验证。
- 线路体验:三网延迟、延迟历史、三网路由追踪详情 - 代理套餐和流媒体套餐购买、续费、增流量。
- 代理订阅查看、订阅链接下载、订阅访问重置 - 购物车、订单、支付状态查询和支付方式切换。
- 流媒体订阅查看与凭据展示 - 代理订阅查看、订阅链接下载、订阅访问重置。
- 通知中心、工单售后、账号资料、邀请码 - 线路体验展示:三网延迟、延迟历史、三网路由追踪。
- 响应式移动端适配 - 流媒体订阅凭据展示。
- 通知中心、工单售后、账号资料、邀请码。
- 暗色/夜间模式和移动端适配。
管理端: 管理端:
- 3x-ui 节点管理:保存面板地址、账号、密码,测试连接并同步入站 - 3x-ui 节点管理:保存面板地址、账号、密码,测试连接并同步入站
- 本地入站展示名维护,套餐绑定同步后的入站线路 - 本地入站展示名维护,套餐绑定同步后的入站线路
- 探测 Token 管理:用于 `/api/agent/latency``/api/agent/trace` - 探测 Token 管理:用于 Agent 上报延迟、路由和节点日志。
- 用户、订单、套餐、订阅、流媒体服务、支付配置 - 用户、订单、套餐、订阅、流媒体服务、支付配置
- 公告、工单、系统设置、审计日志、任务中心、备份恢复 - SMTP 邮件服务设置、注册邮箱验证开关、邮件模板发送。
- 流量视图:基于本地订阅与 3x-ui 同步结果展示客户端用量 - 公告、工单、系统设置、审计日志、任务中心、备份恢复。
- 支持工单上限配置,默认每个用户最多开启 2 个未关闭工单。
- 流量视图:基于本地订阅与 3x-ui 同步结果展示客户端用量。
- 订阅访问风控IP、城市、省/地区、国家变化审查。
- 节点日志风控:基于 Xray access log 分析真实来源 IP、连接数、不同目标数。
- 风控人工处理查看用户、订阅、地图、IP、分析日志生成风险报告选择解除限制或保持封禁/暂停。
节点侧: 节点侧:
- 3x-ui 负责入站、客户端、协议配置和节点运行 - 3x-ui 负责入站、客户端、协议配置和节点运行
- J-Board 通过 3x-ui API 同步入站并执行客户端增删改 - J-Board 通过 3x-ui API 同步入站并执行客户端增删改
- `agent/jboard-agent` 负责三网 TCP 延迟三网路由追踪 - `agent/jboard-agent` 负责三网 TCP 延迟三网路由追踪和可选 Xray access log 风控上报。
- Agent 只读日志文件,不重启 Xray不修改 3x-ui 配置。
## 核心流程 ## 版本与发布规则
节点接入: J-Board 面板和 Agent 使用相对独立的版本节奏。
1. 管理员在 3x-ui 中创建真实入站 - 面板代码变更可以只提交到 `main`,不一定创建 GitHub Release
2. 管理员在 J-Board 添加节点并填写 3x-ui 面板地址、用户名、密码 - Agent 二进制发生变化时,才需要升级 Agent 版本、打 tag、创建 Release并上传 `jboard-agent-linux-amd64``jboard-agent-linux-arm64``SHA256SUMS`
3. J-Board 登录 3x-ui读取入站列表并写入 `NodeInbound` - Agent 安装/升级脚本默认下载 GitHub 最新 Release 中的 Agent 产物
4. 管理员将套餐绑定到已同步入站 - 不要为了普通网站页面或后台文案改动强行更新 Agent tag
5. 用户购买代理套餐后J-Board 调用 3x-ui API 创建客户端,并保存 `NodeClient`
6. 订阅暂停、恢复、删除、重置访问时,同步调用 3x-ui API 更新客户端。
支付开通: 当前项目版本写在 `package.json`Agent 运行时版本写在 `agent/jboard-agent/cmd/agent/main.go`Agent 构建版本写在 `agent/jboard-agent/Makefile`
1. 用户选择套餐、入站和流量规格并创建订单。
2. 支付平台回调后,`src/services/payment/process.ts` 标记订单已支付。
3. `src/services/provision.ts` 创建或更新 `UserSubscription`
4. 代理订阅通过 `src/services/node-panel` 调用 3x-ui 创建或更新客户端。
5. 流媒体订阅分配 `StreamingSlot`
探测上报:
1. 管理员为节点生成探测 Token。
2. 节点运行 `agent/jboard-agent`,配置 `SERVER_URL``AUTH_TOKEN`
3. 探测程序定时调用 `POST /api/agent/latency``POST /api/agent/trace`
4. J-Board 按 Token 匹配节点并更新延迟、历史和路由数据。
## 技术栈 ## 技术栈
- Next.js 16 App Router + React 19 - Next.js 16 App Router + React 19
- Prisma 7 + PostgreSQL 16 - Prisma 7 + PostgreSQL 16
- NextAuth 4 Credentials + Cloudflare Turnstile - NextAuth 4 Credentials
- Redis 7 - Redis 7
- Tailwind CSS 4 + Base UI + Sonner + Recharts - Tailwind CSS 4 + Base UI + Sonner + Recharts
- Go probe agent - Nodemailer SMTP 邮件
- MaxMind MMDB GeoIP
- Go jboard-agent
- Docker / Docker Compose - Docker / Docker Compose
## 目录 注意:本项目使用的 Next.js 版本包含和旧版本不同的约定。开发前请阅读 `AGENTS.md`,并按 `node_modules/next/dist/docs/` 中的当前文档实现。
- `src/app`页面、布局、Route Handlers ## 目录结构
- `src/actions`Server Actions负责写操作、权限校验、审计和缓存刷新
- `src/services`:领域服务与第三方适配 | 路径 | 说明 |
- `src/services/node-panel`3x-ui 面板适配层 | --- | --- |
- `src/services/provision.ts`:支付成功后的订阅开通与 3x-ui 客户端同步 | `src/app` | 页面、布局、Route Handlers。 |
- `src/services/subscription.ts`:订阅内容生成 | `src/actions` | Server Actions负责写操作、权限校验、审计和缓存刷新。 |
- `src/lib`Prisma、鉴权、加密、Turnstile、通用工具 | `src/services` | 领域服务与第三方适配。 |
- `prisma/schema.prisma`:数据模型事实源 | `src/services/node-panel` | 3x-ui 面板适配层。 |
- `agent/jboard-agent`:延迟与线路探测程序 | `src/services/provision.ts` | 支付成功后的订阅开通与 3x-ui 客户端同步。 |
- `docs/API.md`HTTP 接口与 Server Actions 参考 | `src/services/subscription-risk.ts` | 订阅访问与节点日志风控判定。 |
- `docs/openapi.yaml`:对外 HTTP 接口的 OpenAPI 描述 | `src/services/subscription-risk-review.ts` | 风控事件证据整理、报告生成辅助。 |
| `src/lib` | Prisma、鉴权、加密、Turnstile、GeoIP、工具函数。 |
| `prisma/schema.prisma` | 数据模型事实源。 |
| `data/GeoLite2-City.mmdb` | 默认 GeoIP 城市库。 |
| `agent/jboard-agent` | Go Agent 源码、构建脚本和 Agent 文档。 |
| `scripts/install-jboard-panel.sh` | 面板一键安装向导。 |
| `scripts/upgrade-jboard-panel.sh` | 面板升级脚本。 |
| `scripts/install-jboard-agent.sh` | Agent 安装脚本。 |
| `scripts/upgrade-jboard-agent.sh` | Agent 升级脚本。 |
| `docs/API.md` | HTTP 接口与 Server Actions 参考。 |
| `docs/openapi.yaml` | 对外 HTTP 接口 OpenAPI 描述。 |
## 环境变量 ## 环境变量
`.env.example` 为准。生产部署推荐直接使用一键脚本生成 `.env`,手动配置时重点确认这些值: `.env.example` 为准。生产部署推荐使用一键脚本生成 `.env`,手动配置时重点确认下列变量。
| 变量 | 用途 | 说明 | | 变量 | 用途 | 说明 |
| --- | --- | --- | | --- | --- | --- |
| `APP_PORT` | 面板监听端口 | 默认 `3000`。反向代理应转发到 `http://127.0.0.1:APP_PORT`。 | | `APP_PORT` | 面板监听端口 | 默认 `3000`。反向代理应转发到 `http://127.0.0.1:APP_PORT`。 |
| `SITE_NAME` | 站点名称 | 初始化系统设置和邮件模板会使用。 | | `SITE_NAME` | 站点名称 | 初始化系统设置和邮件模板会使用。 |
| `NEXTAUTH_URL` | 网站访问地址 | 必须填写准备反代到面板的正式域名,例如 `https://panel.example.com`。不要填容器内地址。 | | `NEXTAUTH_URL` | 网站访问地址 | 必须填写准备反代到面板的正式域名,例如 `https://panel.example.com`。不要填 `localhost`、容器名或内网地址。 |
| `SUBSCRIPTION_URL` | 订阅访问地址 | 可选。用于生成客户端订阅链接,例如 `https://sub.example.com`;留空时复用 `NEXTAUTH_URL`如果使用独立订阅域名,也要反代到同一个面板服务。 | | `SUBSCRIPTION_URL` | 订阅访问地址 | 可选。用于生成客户端订阅链接,例如 `https://sub.example.com`;留空时复用 `NEXTAUTH_URL`。 |
| `NEXTAUTH_SECRET` | 登录会话密钥 | 生产环境必须使用随机长字符串。 | | `NEXTAUTH_SECRET` | 登录会话密钥 | 生产环境必须使用随机长字符串。 |
| `ENCRYPTION_KEY` | 敏感信息加密密钥 | 至少 32 字节。生产使用后不要更换,否则 3x-ui 密码、探测 Token、流媒体凭据等已加密数据会无法解密。 | | `ENCRYPTION_KEY` | 敏感信息加密密钥 | 至少 32 字节。生产使用后不要更换,否则 3x-ui 密码、探测 Token、SMTP 密码、流媒体凭据等已加密数据会无法解密。 |
| `DATABASE_URL` | PostgreSQL 连接 | 本地工具使用Docker 部署时 Compose 会覆盖为容器内数据库地址。 | | `DATABASE_URL` | PostgreSQL 连接 | 本地工具使用Docker 部署时 Compose 会覆盖为容器内数据库地址。 |
| `POSTGRES_PASSWORD` | Docker PostgreSQL 密码 | 一键脚本会自动生成。 | | `POSTGRES_PASSWORD` | Docker PostgreSQL 密码 | 一键脚本会自动生成。 |
| `REDIS_URL` | Redis 连接 | 本地工具使用Docker 部署时 Compose 会覆盖为容器内 Redis 地址。 | | `REDIS_URL` | Redis 连接 | 本地工具使用Docker 部署时 Compose 会覆盖为容器内 Redis 地址。 |
| `GEOIP_MMDB_PATH` | GeoIP 城市库 | 默认 `data/GeoLite2-City.mmdb`。可换成自己的 MaxMind City MMDB。 |
| `ADMIN_EMAIL` / `ADMIN_PASSWORD` / `ADMIN_NAME` | 初始管理员 | 首次 `db:seed` 创建管理员账号。已有数据库不会强制重置旧管理员密码。 | | `ADMIN_EMAIL` / `ADMIN_PASSWORD` / `ADMIN_NAME` | 初始管理员 | 首次 `db:seed` 创建管理员账号。已有数据库不会强制重置旧管理员密码。 |
SMTP 邮件服务、注册邮箱验证开关、支付方式、3x-ui 节点等业务配置在管理后台填写,不建议写进 `.env` SMTP 邮件服务、注册邮箱验证开关、支付方式、3x-ui 节点等业务配置在管理后台填写,不建议写进 `.env`
## 本地开发 ## 一键部署
适合全新 Linux 服务器。脚本会安装基础依赖、安装 Docker 与 Compose 插件、拉取代码、生成 `.env`、初始化数据库并启动面板。
```bash ```bash
npm install bash <(curl -fsSL https://raw.githubusercontent.com/JetSprow/J-Board/main/scripts/install-jboard-panel.sh)
cp .env.example .env
npm run db:push
npm run db:seed
npm run dev
``` ```
默认管理员账号 脚本会交互询问
- 邮箱:`admin@jboard.local` | 问题 | 如何填写 |
- 密码:`admin123`
常用检查:
```bash
npx prisma generate
npx tsc --noEmit
npm run lint
npm run build
```
数据库变更:
- 修改 `prisma/schema.prisma` 后运行 `npx prisma generate`
- 使用 `npm run db:push` 同步 schema 到数据库
- 不维护 Prisma migrations不提交迁移脚本
- 删除字段或模型时同步清理引用、文档和导出逻辑
## 部署
### 一键部署(推荐)
适合全新的 Linux 服务器。脚本会自动安装 Docker 与 Compose 插件,拉取代码,询问并生成 `.env`,初始化数据库,启动面板,最后输出访问地址、反代目标和管理员账号。
```bash
curl -fsSL https://raw.githubusercontent.com/JetSprow/J-Board/main/scripts/install-jboard-panel.sh | bash
```
脚本会询问这些信息;直接回车即可使用默认值或自动生成值:
| 提示项 | 含义 |
| --- | --- | | --- | --- |
| 安装目录 | 默认 `/opt/jboard`;如果在仓库内运行脚本则默认当前仓库。 | | 安装目录 | 默认 `/opt/jboard`;如果在仓库内运行脚本则默认当前仓库。 |
| 站点名称 | 面板标题、邮件模板和初始化系统设置会使用。 | | 站点名称 | 面板标题、邮件模板和初始化系统设置会使用。 |
| 网站访问地址 | 你准备反向代理到本机 `3000` 端口的面板域名,例如 `https://panel.example.com`。没有域名时可先用 `http://服务器IP:3000` 测试。 | | 网站访问地址 | 你准备反向代理到本机 `3000` 端口的面板域名,例如 `https://panel.example.com`。没有域名时可先用 `http://服务器IP:3000` 测试。 |
| 订阅访问地址 | 用于生成 Clash/V2rayN/Shadowrocket 等客户端订阅链接。可与网站访问地址相同,也可填独立订阅域名,例如 `https://sub.example.com`。 | | 订阅访问地址 | 用于生成 Clash/V2rayN/Shadowrocket 等客户端订阅链接。可以和网站地址相同,也可填独立订阅域名,例如 `https://sub.example.com`。 |
| 本机监听端口 | 默认 `3000`Nginx/Caddy/宝塔反代目标就是 `http://127.0.0.1:3000`。 | | 本机监听端口 | 默认 `3000`NginxCaddy宝塔或 1Panel 的反代目标就是 `http://127.0.0.1:3000`。 |
| 管理员邮箱和密码 | 首次初始化会创建该管理员,脚本完成后会再次打印。 | | 管理员邮箱和密码 | 首次初始化会创建该管理员,脚本完成后会再次打印。 |
| PostgreSQL 密码、`NEXTAUTH_SECRET``ENCRYPTION_KEY` | 可手动输入;回车会自动生成安全值。 | | PostgreSQL 密码、`NEXTAUTH_SECRET``ENCRYPTION_KEY` | 可手动输入;回车会自动生成安全值。 |
也可以环境变量覆盖默认行为: 也可以通过环境变量覆盖默认行为:
```bash ```bash
APP_DIR=/opt/jboard GH_REPO=JetSprow/J-Board BRANCH=main bash <(curl -fsSL https://raw.githubusercontent.com/JetSprow/J-Board/main/scripts/install-jboard-panel.sh) APP_DIR=/opt/jboard GH_REPO=JetSprow/J-Board BRANCH=main bash <(curl -fsSL https://raw.githubusercontent.com/JetSprow/J-Board/main/scripts/install-jboard-panel.sh)
``` ```
脚本完成后,你会看到类似信息 脚本完成后会输出
```text ```text
访问地址https://panel.example.com 访问地址https://panel.example.com
@@ -180,39 +160,9 @@ APP_DIR=/opt/jboard GH_REPO=JetSprow/J-Board BRANCH=main bash <(curl -fsSL https
管理员密码:自动生成或你输入的密码 管理员密码:自动生成或你输入的密码
``` ```
### 反向代理 请把管理员密码保存到密码管理器。已有数据库重复部署时,脚本会尽量沿用现有配置,不会随意重置管理员。
`NEXTAUTH_URL` 和后台“系统设置 -> 网站 URL”都应该填写面板公网域名也就是你准备给用户访问、并反向代理到 J-Board 的域名。不要填写 `localhost`、容器名或内网地址。 ## 手动 Docker 部署
`SUBSCRIPTION_URL` 和后台“系统设置 -> 订阅 URL”只用于生成客户端订阅链接。它可以和网站 URL 相同;如果你想单独做 Cloudflare/WAF/访问风控,建议使用 `https://sub.example.com` 这类独立域名,并把它也反向代理到同一个 J-Board 服务。独立订阅域名只需要承载 `/api/subscription/*`,后续可以在反代或 WAF 层对其他路径返回 404。
Nginx 示例:
```nginx
server {
listen 80;
server_name panel.example.com sub.example.com;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
```
正式上线建议再用 Certbot、宝塔、1Panel、Caddy 或 CDN 申请 HTTPS 证书,然后把 `NEXTAUTH_URL` 改为 `https://panel.example.com`。如果单独使用订阅域名,把 `SUBSCRIPTION_URL` 或后台订阅 URL 改为 `https://sub.example.com`
订阅域名套 Cloudflare 时,源站应只允许 Cloudflare 回源或通过 Cloudflare Tunnel 暴露服务,并正确传递 `CF-Connecting-IP` / `X-Forwarded-For`。否则后续订阅访问风控中的真实 IP 可能被直连源站请求伪造。
J-Board 会记录订阅 API 的真实 IP、User-Agent 和可用的地理位置头,并按后台“系统设置 -> 订阅访问风控”配置执行限流、跨城市/省份告警与自动暂停。默认规则保持为24 小时内 4 个城市警告、5 个城市暂停2 个省/地区警告、3 个省/地区暂停2 个国家/地区警告、3 个国家/地区暂停IP 180 次/小时、订阅 60 次/小时。管理员可以关闭风控总控或关闭自动暂停改为只记录警告也可以在后台“订阅风控”查看关联用户、订阅、IP、地区统计并将事件标记为待处理、已确认或已解决必要时可人工恢复被暂停的订阅。项目内置 `data/GeoLite2-City.mmdb` 作为本地 GeoIP 城市库,默认通过 `GEOIP_MMDB_PATH=data/GeoLite2-City.mmdb` 读取;如果反代或 CDN 已传地理位置头,系统优先使用请求头,并用 MMDB 补齐缺失字段。Cloudflare 场景建议在 Rules -> Settings -> Managed Transforms 开启 Add visitor location headers让回源请求带上 `cf-ipcity``cf-region``cf-region-code` 等字段;未提供城市/省份字段且 MMDB 不可用时,系统只记录 IP不会触发地区变化规则。
### 手动 Docker 部署
首次启动: 首次启动:
@@ -241,21 +191,53 @@ docker compose up -d app
常用排障: 常用排障:
- 查看状态:`docker compose ps` ```bash
- 查看日志:`docker compose logs -f app` docker compose ps
- 页面仍是旧版本:确认已执行 `docker compose build init app``docker compose up -d app` docker compose logs -f app
- Schema 没有生效:单独运行 `docker compose --profile setup run --rm init sh -lc 'npm run db:push'` docker compose --profile setup run --rm init sh -lc 'npm run db:push'
- 登录回调、邮件链接或支付回跳出现 `localhost`:检查 `.env` 里的 `NEXTAUTH_URL` 和后台系统设置里的网站 URL。 ```
- 订阅链接仍然使用主站域名:检查 `.env` 里的 `SUBSCRIPTION_URL` 或后台系统设置里的订阅 URL后台配置优先于环境变量。
### 部署后检查清单 如果页面仍是旧版本,确认已执行 `docker compose build init app``docker compose up -d app`。如果 schema 没生效,单独运行 `npm run db:push` 对应的 setup 命令。
1. 登录 `/admin`,进入“系统设置”,确认网站 URL 是面板反代域名,订阅 URL 是你准备给客户端拉取订阅的域名。 ## 反向代理与域名
2. 配置 SMTP 邮件服务并点击“测试”,再按需要开启注册邮箱验证。
3. 进入“支付配置”,填写并启用至少一种支付方式 `NEXTAUTH_URL` 和后台“系统设置 -> 网站 URL”都应该填写面板公网域名也就是给用户访问、并反向代理到 J-Board 的域名。不要填写 `localhost`、容器名或内网地址,否则登录回调、邮件链接、支付回跳和退出登录提示可能出现错误地址
4. 添加 3x-ui 节点,测试连接并同步入站。
5. 创建套餐,绑定入站或流媒体服务。 `SUBSCRIPTION_URL` 和后台“系统设置 -> 订阅 URL”只用于生成客户端订阅链接。它可以和网站 URL 相同;如果希望单独做 Cloudflare/WAF/访问风控,建议使用独立订阅域名,例如 `https://sub.example.com`,并把它也反向代理到同一个 J-Board 服务。
6. 用普通用户注册、下单、支付、查看订阅,走一遍完整流程。
Nginx 示例:
```nginx
server {
listen 80;
server_name panel.example.com sub.example.com;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
```
正式上线建议使用 Certbot、宝塔、1Panel、Caddy 或 CDN 配置 HTTPS。订阅域名套 Cloudflare 时,源站建议只允许 Cloudflare 回源或通过 Cloudflare Tunnel 暴露,并正确传递 `CF-Connecting-IP` / `X-Forwarded-For`。如果源站允许绕过 Cloudflare 直连,订阅访问风控中的真实 IP 可能被伪造。
## 后台初始化清单
1. 登录 `/admin`,进入“系统设置”,确认网站 URL 和订阅 URL。
2. 配置 SMTP 邮件服务并点击“测试发信”。
3. 按需要开启注册邮箱验证。忘记密码和邮箱变更也会使用 SMTP。
4. 进入“支付配置”,填写并启用至少一种支付方式。
5. 添加 3x-ui 节点,测试连接并同步入站。
6. 创建代理套餐,绑定入站;或创建流媒体服务和套餐。
7. 在节点页生成探测 Token安装 Agent。
8. 用普通用户注册、下单、支付、查看订阅,走一遍完整流程。
9. 进入“订阅风控”确认地图、IP、分析日志、人工操作按钮都能正常展示。
可以展示给用户的常用入口: 可以展示给用户的常用入口:
@@ -264,10 +246,23 @@ docker compose up -d app
- 套餐商店:`https://你的域名/store` - 套餐商店:`https://你的域名/store`
- 用户中心:`https://你的域名/dashboard` - 用户中心:`https://你的域名/dashboard`
- 订阅列表:`https://你的域名/subscriptions` - 订阅列表:`https://你的域名/subscriptions`
- 工单中心:`https://你的域名/support`
## 邮件与邮箱验证
SMTP 配置在后台“系统设置”中完成,密码会加密保存在数据库中。支持的邮件场景包括:
- 注册邮箱验证,可由管理员开启或关闭。
- 忘记密码重置链接。
- 修改邮箱验证。
- 管理员测试发信。
- 风控报告发送和通知辅助。
建议使用专用发信邮箱或应用专用密码。Gmail、企业邮箱和大多数 SMTP 服务都可以使用 `host + port + user + password + from` 的方式接入。生产环境请优先使用 587 STARTTLS 或服务商推荐端口。
## 支付配置 ## 支付配置
支付配置在后台 `/admin/payments` 完成,密钥会保存在数据库中,不写入 `.env`,也不要提交到仓库或截图外传。创建订单时,系统会根据用户选择的支付方式生成支付链接、二维码或链上收款信息;支付成功后进入 `src/services/payment/process.ts` 完成订单确认和订阅开通。 支付配置在后台 `/admin/payments` 完成,密钥会加密保存在数据库中,不写入 `.env`,也不要提交到仓库或截图外传。创建订单时,系统会根据用户选择的支付方式生成支付链接、二维码或链上收款信息;支付成功后进入 `src/services/payment/process.ts` 完成订单确认和订阅开通。
| 支付方式 | 适用场景 | 必填信息 | 回调 / 查询说明 | | 支付方式 | 适用场景 | 必填信息 | 回调 / 查询说明 |
| --- | --- | --- | --- | | --- | --- | --- | --- |
@@ -277,21 +272,54 @@ docker compose up -d app
支付上线前建议: 支付上线前建议:
- 在支付平台后台把通知域名、回跳域名、应用网关白名单设置为你的公网域名。 - 在支付平台后台把通知域名、回跳域名、应用网关白名单设置为公网域名。
- 先创建低金额测试套餐,确认“创建订单 -> 支付 -> 回调/查询 -> 自动开通订阅”完整可用。 - 先创建低金额测试套餐,确认“创建订单 -> 支付 -> 回调/查询 -> 自动开通订阅”完整可用。
- 易支付 API 地址不要带尾部路径,例如填 `https://pay.example.com`,系统会自动请求 `/mapi.php``/submit.php``/api.php` - 易支付 API 地址不要带尾部路径,例如填 `https://pay.example.com`,系统会自动请求 `/mapi.php``/submit.php``/api.php`
- 支付宝密钥可以填写纯 key 内容或 PEM 格式;系统会自动补 PEM 包装。 - 支付宝密钥可以填写纯 key 内容或 PEM 格式;系统会自动补 PEM 包装。
- USDT TRC20 按金额匹配入账,测试时避免短时间出现多笔完全相同金额。 - USDT TRC20 按金额匹配入账,测试时避免短时间出现多笔完全相同金额。
## 节点与探测 ## 节点、3x-ui 与 Agent
节点接入流程:
1. 在 VPS 安装并配置 3x-ui确认面板 API 可访问。 1. 在 VPS 安装并配置 3x-ui确认面板 API 可访问。
2. 管理后台添加 3x-ui 节点 2. 3x-ui 中创建真实入站
3. 保存后 J-Board 会登录 3x-ui 并同步入站 3. 管理后台添加 3x-ui 节点,填写面板地址、用户名和密码
4. 在代理套餐中绑定已同步入站 4. 保存后 J-Board 会登录 3x-ui 并同步入站到 `NodeInbound`
5. 如需前台展示延迟/线路,点击“生成探测 Token”复制弹窗里的一键安装命令到节点执行 5. 在代理套餐中绑定已同步入站
6. 用户购买代理套餐后J-Board 调用 3x-ui API 创建客户端,并保存 `NodeClient`
7. 订阅暂停、恢复、删除、重置访问时,同步调用 3x-ui API 更新客户端。
8. 如需前台展示延迟、线路和节点日志风控,点击“生成探测 Token”复制一键安装命令到节点执行。
探测程序也可手动运行 Agent 安装脚本会
- 下载 GitHub Release 中对应架构的 Agent 二进制。
- 安装或复用 `nexttrace`
- 自动查找 `/usr/local/x-ui/access.log` 等常见 Xray access log 路径。
- 创建 `/var/lib/jboard-agent``/var/log/jboard`
- 尝试让 Agent 具有 access log 读取权限。
- 写入 `/etc/jboard-agent.env`
- 停用并移除旧的 Agent systemd 服务,避免冲突。
- 写入并启动 `jboard-agent.service`
节点机常用命令:
```bash
systemctl status jboard-agent --no-pager -l
journalctl -u jboard-agent -n 100 --no-pager
journalctl -u jboard-agent -f --no-pager
journalctl -u jboard-agent -f --no-pager | grep --line-buffered xray-log
cat /etc/jboard-agent.env
cat /var/lib/jboard-agent/xray-log-state.json
```
升级 Agent
```bash
curl -fsSL https://raw.githubusercontent.com/JetSprow/J-Board/main/scripts/upgrade-jboard-agent.sh | bash
```
如果只想手动运行 Agent
```bash ```bash
SERVER_URL=https://your-domain.com \ SERVER_URL=https://your-domain.com \
@@ -299,14 +327,63 @@ AUTH_TOKEN=后台生成的探测Token \
./jboard-agent ./jboard-agent
``` ```
可选变量: 更多 Agent 说明见 `agent/jboard-agent/README.md`
- `LATENCY_INTERVAL`:默认 `5m` ## 订阅访问风控
- `TRACE_INTERVAL`:默认 `30m`
路由探测依赖 `nexttrace`。没有该命令时,延迟探测仍可运行,路由探测会记录错误日志 J-Board 的订阅风控分两层
## 备份与安全 第一层是订阅 API 访问风控。用户或客户端拉取 `/api/subscription/*` 时,系统记录真实 IP、User-Agent、国家、省/地区、城市、经纬度,并按后台配置判断:
- 单 IP 每小时访问次数。
- 单订阅 token 每小时访问次数。
- 24 小时窗口内不同城市数量。
- 24 小时窗口内不同省/地区数量。
- 24 小时窗口内不同国家/地区数量。
第二层是节点真实连接风控。Agent 读取 Xray access log将日志里的 `email: user@example.com-xxxx` 匹配到本地 `NodeClient.email`,再归属到用户和订阅。系统记录:
- 真实来源 IP。
- 真实来源 IP 的 GeoIP。
- 入站 tag。
- tcp/udp。
- 样本目标域名或 IP。
- 目标端口。
- 聚合窗口内连接数。
- 聚合窗口内不同目标数。
- 首次和最近连接时间。
管理员可在“系统设置 -> 订阅访问风控”中配置总开关、自动暂停开关、窗口时长、城市/省/国家阈值、IP/订阅访问频率阈值,以及节点日志风控中的连接数和不同目标数阈值。
默认规则保持为:
- 24 小时内 4 个城市警告5 个城市暂停。
- 2 个省/地区警告3 个省/地区暂停。
- 2 个国家/地区警告3 个国家/地区暂停。
- IP 180 次/小时,订阅 60 次/小时。
- 节点日志风控默认开启,连接数和不同目标数按 Agent 单次聚合窗口计算。
风控事件会进入后台“订阅风控”。管理员可以:
- 查看关联用户和订阅详情。
- 查看 IP、国家、省/地区、城市统计。
- 在世界地图上查看可识别坐标点。
- 展开分析日志,看到每条证据的 IP、时间、来源、Xray 解析详情、连接数和不同目标数。
- 生成风险报告。
- 选择是否发送到用户端。
- 解除限制或保持封禁/暂停。
用户收到管理员发送的风险报告后,会看到全屏不可关闭的限制通知,只能新建工单联系客服,不能继续进行其他用户端操作。
## GeoIP 与 Cloudflare
项目内置 `data/GeoLite2-City.mmdb` 作为本地 GeoIP 城市库,默认通过 `GEOIP_MMDB_PATH=data/GeoLite2-City.mmdb` 读取。系统会优先使用反向代理或 CDN 提供的地理位置头,并用 MMDB 补齐缺失字段。
Cloudflare 场景建议在 Rules -> Settings -> Managed Transforms 开启 Add visitor location headers让回源请求带上 `cf-ipcity``cf-region``cf-region-code` 等字段。未提供城市/省份字段且 MMDB 不可用时,系统只记录 IP不会触发地区变化规则。
如果网站域名和订阅域名相同,系统只统计订阅 API 访问,不会把普通网站浏览计入订阅风控。
## 备份与恢复
下载 SQL 备份: 下载 SQL 备份:
@@ -316,29 +393,113 @@ docker compose exec -T db pg_dump -U jboard jboard > backup_$(date +%Y%m%d_%H%M%
后台也可通过 `/admin/backups` 导出或恢复数据库。恢复前务必先保存当前数据库备份。 后台也可通过 `/admin/backups` 导出或恢复数据库。恢复前务必先保存当前数据库备份。
安全建议: 建议:
- 不要提交 `.env`、探测 Token、3x-ui 密码、支付密钥 - 定期备份 PostgreSQL volume。
- 数据库备份里包含用户、订单和支付配置,建议加密保存并限制下载权限 - 将备份加密保存。
- 生产环境不要公开 PostgreSQL 和 Redis 端口 - 备份恢复后立即检查管理员登录、支付配置、节点密码、SMTP、订阅 URL 和 Agent 上报。
- 3x-ui 面板建议限制来源 IP 或使用反向代理鉴权
- `ENCRYPTION_KEY` 一旦生产使用不要随意更换,否则已加密数据会无法解密
## 开发原则 ## 本地开发
- 节点入站与客户端运行配置以 3x-ui 为准J-Board 只保存售卖镜像 ```bash
- 后端只保留探测上报接口,不再新增节点控制面接口 npm install
- Server Actions 负责权限、校验、审计和缓存刷新 cp .env.example .env
- Route Handlers 仅用于外部 HTTP 接口或文件下载 npm run db:push
- 重要副作用必须记录审计日志或任务记录 npm run db:seed
npm run dev
```
默认管理员账号:
- 邮箱:`admin@jboard.local`
- 密码:`admin123`
常用检查:
```bash
npx prisma generate
npx tsc --noEmit
npm run lint
npm run build
```
数据库变更:
- 修改 `prisma/schema.prisma` 后运行 `npm run db:push`
- 生产 Docker 部署更新后,运行 `docker compose --profile setup run --rm init sh -lc 'npm run db:push'`
- 当前项目使用 `prisma db push --accept-data-loss`,上线前请确认 schema 变更不会误删重要数据。
Agent 开发:
```bash
cd agent/jboard-agent
go test ./...
make build-linux
shasum -a 256 jboard-agent-linux-amd64 jboard-agent-linux-arm64 > SHA256SUMS
```
## 安全建议
- 不要提交 `.env`、探测 Token、3x-ui 密码、SMTP 密码、支付密钥。
- 数据库备份包含用户、订单、支付配置、节点凭据和邮件配置,建议加密保存并限制下载权限。
- 生产环境不要公开 PostgreSQL 和 Redis 端口。
- 3x-ui 面板建议限制来源 IP 或使用反向代理鉴权。
- `ENCRYPTION_KEY` 一旦生产使用不要随意更换。
- 管理后台账号建议使用强密码和专用邮箱。
- 订阅域名套 CDN 时应避免源站裸露,否则真实 IP 风控可信度会下降。
- Agent 只读 Xray access log但日志中包含用户 IP、访问目标和 client email应按敏感数据处理。
## 常见问题
### 登录、退出或邮件链接出现 localhost
检查 `.env` 中的 `NEXTAUTH_URL` 和后台系统设置中的网站 URL。后台配置优先于环境变量。生产环境必须填写公网域名。
### 订阅链接使用了错误域名
检查 `.env` 中的 `SUBSCRIPTION_URL` 和后台系统设置中的订阅 URL。后台配置优先于环境变量。
### 点击测试发信报错
先确认 SMTP 是否启用、Host/Port/User/Password/From 是否正确。Gmail 等服务通常需要应用专用密码。生产环境隐藏原始异常时,可查看 `docker compose logs -f app`
### 用户不验证邮箱也能注册
确认后台“注册邮箱验证”已经开启,并检查 SMTP 是否启用。邮箱验证开启后,新用户会进入待验证状态,必须通过邮件链接激活。
### Agent 没有 xray-log 输出
先看 Agent 是否运行:
```bash
systemctl status jboard-agent --no-pager -l
journalctl -u jboard-agent -n 100 --no-pager
```
再确认 access log 状态:
```bash
cat /etc/jboard-agent.env | grep XRAY
cat /var/lib/jboard-agent/xray-log-state.json
tail -n 50 /usr/local/x-ui/access.log
grep "email:" /usr/local/x-ui/access.log | tail -n 20
```
Agent 默认 `XRAY_LOG_START_AT_END=1`,首次启动会从文件末尾开始,只分析启动后的新连接。需要真实客户端连接节点并产生带 `email:` 的 access log后台才会出现节点真实连接分析。
### Xray client email 带后缀是否有影响
没有影响。J-Board 用户邮箱可能是 `user@example.com`Xray client email 可能是 `user@example.com-cmojtnp3`。节点日志风控用 Xray access log 里的 client email 匹配本地 `NodeClient.email`,再找到真实用户和订阅。不要手动在 3x-ui 改 client email否则会导致日志无法归属。
## 文档 ## 文档
- `docs/API.md`HTTP 接口与 Server Actions 参考 - `docs/API.md`HTTP 接口与 Server Actions 参考
- `docs/openapi.yaml`:对外 HTTP 接口 OpenAPI 3.1 描述 - `docs/openapi.yaml`:对外 HTTP 接口 OpenAPI 3.1 描述
- `agent/jboard-agent/README.md`探测程序说明 - `agent/jboard-agent/README.md`Agent 安装、升级、日志与排障说明
- `AGENTS.md`:给代码协作 Agent 的仓库规则。
## 请我喝杯咖啡 ## 请我喝杯咖啡
![JsPYre9xe7W1Ad6mwPgrfuXBYJ8iy6oC.webp](https://cdn.nodeimage.com/i/XuxZ7NoLsc51fS99S6AtMB9K9ekTTQcD.webp) ![JsPYre9xe7W1Ad6mwPgrfuXBYJ8iy6oC.webp](https://cdn.nodeimage.com/i/XuxZ7NoLsc51fS99S6AtMB9K9ekTTQcD.webp)
USDT-TRC20: TQfaGEBdnB89V4y6R6bypZXx7Za5QfXBCi USDT-TRC20: TQfaGEBdnB89V4y6R6bypZXx7Za5QfXBCi

View File

@@ -1,12 +1,289 @@
# jboard-agent # jboard-agent
`jboard-agent` 以旁路方式负责节点探测和可选的 Xray access log 风控上报: `jboard-agent` 是 J-Board 的节点侧旁路程序。它运行在节点 VPS 上,负责节点体验和节点真实连接证据上报到 J-Board。
- 三网 TCP 延迟:`POST /api/agent/latency` 它做三件事:
- 三网路由跟踪:`POST /api/agent/trace`
- Xray access log 聚合:`POST /api/agent/node-access`,安装/升级脚本会自动探测并写入 `XRAY_ACCESS_LOG_PATH`
节点入站、客户端开通、暂停、删除、流量限制等配置均由 3x-ui 面板维护。Agent 只读日志文件,不修改 3x-ui 配置、不重启 Xray。 - 三网 TCP 延迟探测:`POST /api/agent/latency`
- 三网路由追踪:`POST /api/agent/trace`
- Xray access log 聚合:`POST /api/agent/node-access`
它不做这些事:
- 不创建、删除或修改 3x-ui 入站。
- 不创建、删除或修改 Xray 客户端。
- 不重启 3x-ui 或 Xray。
- 不接管节点流量。
- 不作为公共代理或透明代理。
节点入站、客户端开通、暂停、删除、流量限制等配置均由 3x-ui 面板维护。Agent 只读日志文件,并通过 J-Board 的 Agent Token 上报结果。
## 工作方式
```text
jboard-agent
├─ LatencyLoop定时 TCP connect 三网目标
├─ TraceLoop定时调用 nexttrace 获取三网路由
└─ XrayAccessLogLoop读取 Xray access log聚合真实来源 IP、连接数和不同目标数
J-Board /api/agent/*
后台节点体验、订阅风控、分析日志、风险报告
```
Agent 使用 `AUTH_TOKEN` 认证。这个 token 在 J-Board 后台节点页生成,服务端会通过它匹配到具体 `NodeServer`
## 安装
推荐在 J-Board 后台“节点管理”中点击生成 Agent Token然后复制弹窗中的一键安装命令到节点机执行。安装脚本会自动完成
- 下载 GitHub Release 中对应架构的二进制。
- 校验 `SHA256SUMS`
- 安装或复用 `nexttrace`
- 自动查找 Xray access log。
- 创建 `/var/lib/jboard-agent``/var/log/jboard`
- 写入 `/etc/jboard-agent.env`
- 停用并移除旧的 Agent systemd 服务,避免冲突。
- 写入并启动 `jboard-agent.service`
手动安装命令形如:
```bash
curl -fsSL https://raw.githubusercontent.com/JetSprow/J-Board/main/scripts/install-jboard-agent.sh | SERVER_URL=https://panel.example.com AUTH_TOKEN=你的Token bash
```
如果需要指定 Agent Release
```bash
curl -fsSL https://raw.githubusercontent.com/JetSprow/J-Board/main/scripts/install-jboard-agent.sh | AGENT_TAG=v3.0.2 SERVER_URL=https://panel.example.com AUTH_TOKEN=你的Token bash
```
## 升级
```bash
curl -fsSL https://raw.githubusercontent.com/JetSprow/J-Board/main/scripts/upgrade-jboard-agent.sh | bash
```
升级脚本会读取现有 `/etc/jboard-agent.env`保留服务器地址、Token、探测间隔和 Xray 日志配置,并重新写入当前 systemd service。
升级后确认版本:
```bash
journalctl -u jboard-agent -n 30 --no-pager
```
你应该看到类似:
```text
[agent] jboard-agent v3.0.2 starting in probe-only mode
```
## 环境变量
| 变量 | 默认值 | 说明 |
| --- | --- | --- |
| `SERVER_URL` | 必填 | J-Board 面板公网地址,例如 `https://panel.example.com`。 |
| `AUTH_TOKEN` | 必填 | 后台节点页生成的 Agent Token。 |
| `LATENCY_INTERVAL` | `5m` | 延迟探测间隔,支持 `30s``5m` 或纯秒数。 |
| `TRACE_INTERVAL` | `30m` | 路由探测间隔,支持 `30m` 或纯秒数。 |
| `XRAY_ACCESS_LOG_PATH` | 自动探测 | Xray access log 路径。为空时节点真实连接风控禁用。 |
| `XRAY_LOG_INTERVAL` | `1m` | access log 读取、聚合、上报间隔。 |
| `XRAY_LOG_STATE_FILE` | `/var/lib/jboard-agent/xray-log-state.json` | access log offset 状态文件。 |
| `XRAY_LOG_START_AT_END` | `1` | 首次启动从文件末尾开始,避免上传历史巨量日志;设为 `0` 可从头读取。 |
| `INSTALL_NEXTTRACE` | `1` | 安装脚本是否自动安装 nexttrace。 |
systemd 环境文件默认位于:
```bash
/etc/jboard-agent.env
```
修改环境文件后需要重启:
```bash
systemctl restart jboard-agent
```
## Xray access log
安装/升级脚本会优先查找这些路径:
- `/usr/local/x-ui/access.log`
- `/usr/local/x-ui/bin/access.log`
- `/usr/local/x-ui/xray/access.log`
- `/etc/x-ui/access.log`
- `/etc/x-ui/xray/access.log`
- `/var/log/xray/access.log`
- `/var/log/x-ui/access.log`
- `/opt/3x-ui/access.log`
- `/opt/x-ui/access.log`
- `/usr/local``/etc``/var/log``/opt`、Docker volume 下名称包含 `access.log``xray` 的日志
如果没有找到,脚本会提示你在 3x-ui 的 Xray Config 中开启:
```json
"log": {
"access": "/usr/local/x-ui/access.log",
"error": "/usr/local/x-ui/error.log",
"loglevel": "warning"
}
```
然后重启 x-ui再重跑 Agent 安装或升级脚本。
### 支持的日志格式
Agent 支持常见 Xray access log 格式,包括:
```text
2026/04/29 10:11:12 203.0.113.9:51820 accepted tcp:example.com:443 [proxy-in >> freedom] email: user@example.com-cabc1234
```
也支持 3x-ui/Xray 新格式:
```text
2026/04/29 09:20:05.982584 from 220.240.111.193:59425 accepted tcp:example.com:443 [inbound-17583 >> direct] email: user@example.com-cmojtnp3
2026/04/29 09:20:06.006542 from tcp:220.240.111.193:59433 accepted udp:71.18.167.208:443 [inbound-17583 >> direct] email: user@example.com-cmojtnp3
```
Agent 会解析:
- `sourceIp`:真实来源 IP。
- `clientEmail`Xray client email。
- `inboundTag`:入站 tag例如 `inbound-17583`
- `network``tcp``udp`
- `targetHost` / `targetPort`:样本目标。
- `action``accepted``rejected`
- `connectionCount`:聚合窗口内连接数。
- `uniqueTargetCount`:聚合窗口内不同目标数。
- `firstSeenAt` / `lastSeenAt`:窗口内首次和最近连接时间。
没有 `email:` 的日志会跳过,因为服务端无法把它归属到 J-Board 的 `NodeClient``[api -> api]` 这类 3x-ui 本地 API 通信通常也会跳过。
## Xray client email 与用户邮箱
J-Board 用户邮箱和 Xray client email 不一定完全相同。例如:
```text
J-Board 用户邮箱user@example.com
Xray client emailuser@example.com-cmojtnp3
```
这是正常设计。节点日志风控使用 Xray access log 里的 `email:` 匹配本地 `NodeClient.email`,再找到对应用户和订阅。不要手动在 3x-ui 修改 client email否则日志会无法归属。
## systemd 运维
查看服务状态:
```bash
systemctl status jboard-agent --no-pager -l
```
实时日志:
```bash
journalctl -u jboard-agent -f --no-pager
```
看最近 100 行:
```bash
journalctl -u jboard-agent -n 100 --no-pager
```
只看 Xray 日志采集:
```bash
journalctl -u jboard-agent -f --no-pager | grep --line-buffered xray-log
```
查看配置:
```bash
cat /etc/jboard-agent.env
```
查看 access log offset 状态:
```bash
cat /var/lib/jboard-agent/xray-log-state.json
```
## 排障
### Agent 没有启动
```bash
systemctl status jboard-agent --no-pager -l
journalctl -u jboard-agent -n 100 --no-pager
```
常见原因:
- `/etc/jboard-agent.env` 缺少 `SERVER_URL``AUTH_TOKEN`
- 二进制没有执行权限。
- 旧服务没有清理干净。新安装/升级脚本会自动停用并移除旧服务。
### 没有 `[xray-log]` 输出
这不一定是错误。Agent 只在禁用、报错或成功推送时打印 `xray-log`。如果没有新 access log实时 grep 会一直等待。
按顺序检查:
```bash
cat /etc/jboard-agent.env | grep XRAY
cat /var/lib/jboard-agent/xray-log-state.json
tail -n 50 /usr/local/x-ui/access.log
grep "email:" /usr/local/x-ui/access.log | tail -n 20
```
如果状态文件类似:
```json
{"path":"/usr/local/x-ui/access.log","inode":393262,"offset":180}
```
说明 Agent 已经找到并跟踪日志。它会从 offset 之后继续读。
### access log 只有 `[api -> api]`
例如:
```text
2026/04/29 09:16:07.001315 from 127.0.0.1:43702 accepted tcp:127.0.0.1:62789 [api -> api]
```
这是 3x-ui / Xray 本地 API 通信,不是用户节点连接。你需要让真实客户端连接节点,再查看是否出现带 `email:` 的记录。
### 强制从头重读 access log
仅用于测试。生产环境不建议长期保持从头读取。
```bash
systemctl stop jboard-agent
rm -f /var/lib/jboard-agent/xray-log-state.json
sed -i 's/^XRAY_LOG_START_AT_END=.*/XRAY_LOG_START_AT_END=0/' /etc/jboard-agent.env
systemctl start jboard-agent
journalctl -u jboard-agent -n 100 --no-pager | grep xray-log
```
测试完成后改回:
```bash
sed -i 's/^XRAY_LOG_START_AT_END=.*/XRAY_LOG_START_AT_END=1/' /etc/jboard-agent.env
systemctl restart jboard-agent
```
### 服务端没有收到节点日志风控
检查:
- 后台系统设置是否开启订阅风控总控。
- 后台是否开启节点日志风控。
- access log 是否包含 `email:`
- `email:` 是否与 J-Board 数据库里的 `NodeClient.email` 一致。
- Agent Token 是否属于当前节点。
- 面板日志是否有 `/api/agent/node-access` 的错误。
## 构建 ## 构建
@@ -16,31 +293,27 @@ make build
make build-linux make build-linux
``` ```
## 运行 生成校验和:
```bash ```bash
SERVER_URL=https://your-domain.com \ shasum -a 256 jboard-agent-linux-amd64 jboard-agent-linux-arm64 > SHA256SUMS
AUTH_TOKEN=后台生成的探测Token \
./jboard-agent
``` ```
可选环境变量: ## Release 规则
| 变量 | 默认值 | 说明 | 只有 Agent 代码或 Agent 安装/升级体验需要随二进制发布时,才创建新的 Agent tag 和 GitHub Release。普通面板页面、后台 UI、文档或 Server Action 改动不需要强行更新 Agent release。
| --- | --- | --- |
| `LATENCY_INTERVAL` | `5m` | 延迟探测间隔,支持 `30s``5m` 或秒数 |
| `TRACE_INTERVAL` | `30m` | 路由探测间隔,支持 `30m` 或秒数 |
| `XRAY_ACCESS_LOG_PATH` | 自动探测 | Xray access log 路径;安装/升级脚本会优先查找 `/usr/local/x-ui/access.log` 等常见路径,仍为空时禁用节点真实连接风控 |
| `XRAY_LOG_INTERVAL` | `1m` | 日志读取和聚合上报间隔 |
| `XRAY_LOG_STATE_FILE` | `/var/lib/jboard-agent/xray-log-state.json` | 日志 offset 状态文件 |
| `XRAY_LOG_START_AT_END` | `1` | 首次启动从文件末尾开始,避免上传历史巨量日志;设为 `0` 可从头读取 |
路由探测依赖 `nexttrace` 命令;延迟探测无需额外依赖。 Release 需要包含:
## systemd - `jboard-agent-linux-amd64`
- `jboard-agent-linux-arm64`
- `SHA256SUMS`
推荐从 J-Board 后台节点页复制一键安装命令。该命令会下载 release 二进制、安装 `nexttrace`、自动探测 3x-ui/Xray access log、写入 systemd 服务并启动 安装/升级脚本默认使用 GitHub 最新 Release。需要固定版本时传入 `AGENT_TAG=vX.Y.Z`
## 延迟算法 ## 安全边界
延迟探测使用三组 zstaticcdn 运营商目标,先解析域名再开始计时,只统计 TCP connect 耗时,避免 DNS 抖动混入延迟;当单次结果超过 1000ms 时会额外重试最多 3 次并采用更低的有效结果。 - Agent 只读 Xray access log但日志中包含真实来源 IP、访问目标和 client email应按敏感数据处理。
- Agent Token 等同节点上报凭据,不要外传。
- 节点服务器上不要公开 `/etc/jboard-agent.env`
- 3x-ui 面板建议限制来源 IP 或使用反向代理鉴权。

View File

@@ -1,20 +1,22 @@
# J-Board API # J-Board API 与 Server Actions
本文整理当前有效的 HTTP Route Handlers 和内部 Server Actions。对外 HTTP 结构化描述见 `docs/openapi.yaml` 本文整理 J-Board 当前有效的 HTTP Route Handlers 和内部 Server Actions。HTTP 对外结构化描述见 `docs/openapi.yaml`;本文更偏向工程阅读和排障
## 1. 通用约定 ## 通用约定
- 用户会话NextAuth Cookie - 普通用户身份NextAuth Cookie 会话。
- 管理接口:必须是管理员会话 - 管理员身份NextAuth Cookie 会话,且用户角色为 `ADMIN`
- 探测接口`Authorization: Bearer <probe-token>` - Agent 身份`Authorization: Bearer <agent-token>`
- 返回格式JSON文件下载接口除外 - 返回格式:默认 JSON订阅内容和文件下载接口除外
- 时间字段ISO 8601 字符串 - 时间字段ISO 8601 字符串
- 写操作:必须做权限校验、输入校验、审计记录和必要的 `revalidatePath`
- 3x-ui 密码、Agent Token、SMTP 密码、支付密钥等敏感字段在数据库中加密保存。
## 2. 认证 ## 认证与公开信息
### `POST /api/auth/register` ### `POST /api/auth/register`
注册普通用户。 注册普通用户。是否允许注册、是否必须邀请码、是否需要邮箱验证由后台系统设置控制。
请求体: 请求体:
@@ -28,15 +30,21 @@
} }
``` ```
行为:
- 校验邮箱、密码、邀请码和 Turnstile。
- 当注册邮箱验证开启时,用户会进入 `PENDING_EMAIL` 状态并收到验证邮件。
- 当注册邮箱验证关闭时,用户直接成为可登录用户。
### `GET|POST /api/auth/[...nextauth]` ### `GET|POST /api/auth/[...nextauth]`
NextAuth 内置登录、登出、会话接口。 NextAuth 内置登录、登出、会话接口。
## 3. 公共数据
### `GET /api/public/app-info` ### `GET /api/public/app-info`
返回站点名称、注册策略、维护公告、Turnstile 配置等公开信息 返回站点名称、注册策略、维护公告、Turnstile 配置、网站公开配置等信息。前端登录页、注册页和公共布局会使用它
## 延迟与路由展示
### `GET /api/latency?nodeId=<id>` ### `GET /api/latency?nodeId=<id>`
@@ -44,17 +52,21 @@ NextAuth 内置登录、登出、会话接口。
### `GET /api/latency/history?nodeId=<id>&carrier=telecom&range=7d` ### `GET /api/latency/history?nodeId=<id>&carrier=telecom&range=7d`
返回节点延迟历史`range` 支持 `1d``7d``30d` 返回节点延迟历史`carrier` 通常为 `telecom``unicom``mobile``range` 支持 `1d``7d``30d`
### `GET /api/latency/recommendations`
返回前台线路推荐所需的延迟聚合结果。
### `GET /api/traces?nodeId=<id>` ### `GET /api/traces?nodeId=<id>`
返回节点三网路由追踪结果。 返回节点三网路由追踪结果。服务端会重新归一化历史数据,修正 CN2 GIA、CN2 GT、CMIN2、CMI 等线路分类。
## 4. 支付 ## 支付接口
### `GET /api/payment/providers` ### `GET /api/payment/providers`
返回当前启用的支付方式。 返回当前启用的支付方式。普通用户创建订单或切换支付方式时使用。
### `POST /api/payment/create` ### `POST /api/payment/create`
@@ -69,19 +81,63 @@ NextAuth 内置登录、登出、会话接口。
} }
``` ```
行为:
- 校验订单属于当前用户且仍待支付。
- 根据支付方式生成支付链接、二维码或链上支付信息。
- 记录支付流水,便于后续回调或查询。
### `GET /api/payment/order/{orderId}` ### `GET /api/payment/order/{orderId}`
查询当前用户自己的订单支付状态。 查询当前用户自己的订单支付状态。
### `GET /api/payment/query/{tradeNo}` ### `GET /api/payment/query/{tradeNo}`
按支付流水号查询支付状态。 按支付流水号主动查询支付状态。用于前端轮询或支付平台回调异常时兜底。
### `GET|POST /api/payment/notify/{provider}` ### `GET|POST /api/payment/notify/{provider}`
支付平台异步通知入口。 支付平台异步通知入口。当前 provider 包括:
## 5. 管理导出与节点读取 - `epay`
- `alipay_f2f`
- `usdt_trc20` 的链上入账由查询任务处理,不依赖传统 HTTP 回调。
行为:
- 校验签名或链上入账。
- 标记订单已支付。
- 调用 `src/services/provision.ts` 创建或续费订阅。
- 代理订阅会同步 3x-ui client。
## 订阅与用户资源
### `GET /api/subscription/{id}?token=<downloadToken>`
无需登录,但必须提供合法下载 token。成功返回 `text/plain` 订阅内容。
行为:
- 校验订阅状态、到期时间和 token。
- 记录订阅访问日志和真实 IP。
- 执行订阅访问限流和地区变化风控。
- 当订阅被暂停或风控限制时,返回错误内容或拒绝访问。
### `GET /api/subscription/all`
返回用户聚合订阅内容。用于部分客户端的一键导入或总订阅入口。
### `GET /api/notifications`
返回当前用户通知列表。
### `GET /api/support/attachments/{id}`
工单附件访问接口。要求登录用户是附件所属工单用户本人或管理员。加 `?download=1` 可触发下载。
## 管理读取与导出
以下接口要求管理员会话。
### `GET /api/admin/nodes` ### `GET /api/admin/nodes`
@@ -89,11 +145,11 @@ NextAuth 内置登录、登出、会话接口。
### `GET /api/admin/nodes/{id}/inbounds` ### `GET /api/admin/nodes/{id}/inbounds`
返回指定节点的已同步入站。 返回指定节点的已同步入站。套餐绑定和节点详情页会使用。
### `GET /api/admin/export/config` ### `GET /api/admin/export/config`
导出配置快照,包含站点设置、公告、服务、套餐、节点、入站、支付配置等。 导出配置快照,包含站点设置、公告、服务、套餐、节点、入站、支付配置等。敏感值会按实现规则脱敏或加密保存,不应公开传播。
### `GET /api/admin/export/audit-logs?q=<keyword>` ### `GET /api/admin/export/audit-logs?q=<keyword>`
@@ -101,11 +157,17 @@ NextAuth 内置登录、登出、会话接口。
### `GET /api/admin/backup/database` ### `GET /api/admin/backup/database`
导出 SQL 数据库备份。 导出 SQL 数据库备份。备份包含用户、订单、节点、支付、SMTP 等敏感信息,应加密保存。
## 6. 探测上报 ## Agent 上报接口
以下接口由 `agent/jboard-agent` 调用,探测 Token 存储在 `NodeServer.agentToken` 中并加密保存。 以下接口由 `agent/jboard-agent` 调用。Agent Token 存储在 `NodeServer.agentToken`并加密保存。请求头必须为:
```http
Authorization: Bearer <agent-token>
```
服务端会通过 Token 匹配到具体节点 `nodeId`
### `POST /api/agent/latency` ### `POST /api/agent/latency`
@@ -121,7 +183,11 @@ NextAuth 内置登录、登出、会话接口。
} }
``` ```
行为:更新 `NodeLatency` 并写入 `NodeLatencyLog` 行为:
- 更新 `NodeLatency`
- 写入 `NodeLatencyLog`
- 前台节点延迟、历史图表和推荐会使用这些数据。
### `POST /api/agent/trace` ### `POST /api/agent/trace`
@@ -132,7 +198,17 @@ NextAuth 内置登录、登出、会话接口。
"traces": [ "traces": [
{ {
"carrier": "telecom", "carrier": "telecom",
"hops": [{ "hop": 1, "ip": "*", "geo": "", "latency": 0 }], "hops": [
{
"hop": 1,
"ip": "203.0.113.1",
"geo": "CN",
"latency": 3.5,
"asn": "AS4809",
"owner": "China Telecom CN2",
"isp": "China Telecom"
}
],
"summary": "CN2 GIA", "summary": "CN2 GIA",
"hopCount": 12 "hopCount": 12
} }
@@ -140,53 +216,111 @@ NextAuth 内置登录、登出、会话接口。
} }
``` ```
行为:`nodeId + carrier` 更新 `RouteTrace` 行为:
## 7. 订阅与附件 - 服务端重新分类线路,避免旧 Agent 或 nexttrace 文案导致误判。
-`nodeId + carrier` 更新 `RouteTrace`
- 线路分类会优先识别 CN2 GIA、CN2 GT、CMIN2、CMI 等常见中国方向线路。
### `GET /api/subscription/{id}?token=<downloadToken>` ### `POST /api/agent/node-access`
无需会话,但必须提供合法下载 token。成功返回 `text/plain` 订阅内容 接收 Agent 从 Xray access log 聚合出的真实节点连接事件
### `GET /api/support/attachments/{id}` 请求体:
工单附件访问接口,要求登录用户是附件所属工单用户本人或管理员。加 `?download=1` 可触发下载。 ```json
{
"events": [
{
"clientEmail": "user@example.com-cmojtnp3",
"sourceIp": "220.240.111.193",
"inboundTag": "inbound-17583",
"network": "tcp",
"targetHost": "example.com",
"targetPort": 443,
"action": "accepted",
"connectionCount": 18,
"uniqueTargetCount": 14,
"firstSeenAt": "2026-04-29T09:20:05+10:00",
"lastSeenAt": "2026-04-29T09:20:07+10:00"
}
]
}
```
## 8. Server Actions 行为:
Server Actions 是后台和用户端写操作的主要入口。所有管理动作必须经过 `requireAdmin()`,用户动作必须校验资源归属 - 通过 `clientEmail` 匹配 `NodeClient.email`
- 同时要求该 client 属于当前 Agent Token 对应节点。
- 写入 `SubscriptionAccessLog`,来源标记为“节点真实连接”。
- 使用 `sourceIp` 执行国家、省/地区、城市变化风控。
- 使用 `connectionCount``uniqueTargetCount` 执行节点日志行为风控。
- 创建 `SubscriptionRiskEvent`、通知、审计日志,并在需要时自动暂停订阅。
### 管理端 返回示例:
节点:`src/actions/admin/nodes.ts` ```json
{
"ok": true,
"processed": 1,
"skipped": 0,
"warnings": 0,
"suspended": 0
}
```
- `createNode(formData)`:创建 3x-ui 节点并同步入站 常见跳过原因:
- `updateNode(id, formData)`:更新 3x-ui 节点连接信息并重新同步入站
- `deleteNode(id)`:删除节点及本地关联数据
- `testNodeConnection(id)`:测试 3x-ui 登录并同步入站
- `batchTestNodeConnections(formData)`:批量测试并同步节点
- `updateInboundDisplayName(id, formData)`:修改同步入站的前台展示名称
- `deleteInbound(id)`:仅删除本地入站镜像,不删除 3x-ui 入站
- `generateAgentToken(nodeId)`:生成探测 Token
- `revokeAgentToken(nodeId)`:撤销探测 Token
订阅:`src/actions/admin/subscriptions.ts` - Xray access log 没有 `email:` 字段。
- `email:` 与本地 `NodeClient.email` 不一致。
- 日志来自 `[api -> api]` 这类 3x-ui 本地 API 通信。
- 后台关闭了订阅风控总控或节点日志风控。
- `suspendSubscription(id)`:暂停订阅,并通过 3x-ui 禁用代理客户端 ## Server Actions
- `activateSubscription(id)`:恢复订阅,并通过 3x-ui 启用代理客户端
- `cancelSubscription(id)`:取消订阅
- `deleteSubscriptionPermanently(id)`:删除订阅,并通过 3x-ui 删除代理客户端
- `reassignStreamingSlot(...)`:调整流媒体槽位
- `batchSubscriptionOperation(formData)`:批量处理订阅
订单:`src/actions/admin/orders.ts` Server Actions 是后台和用户端写操作的主要入口。它们不是公开 HTTP API不建议第三方直接调用。
- `confirmOrder(orderId)`:手动确认订单并触发开通 ### 管理端 Actions
- `cancelOrder(orderId)`:取消订单
- `updateOrderReview(...)`:更新风控/复核状态
- `batchOrderOperation(formData)`:批量操作订单
其他管理动作: #### 节点:`src/actions/admin/nodes.ts`
- `createNode(formData)`:创建 3x-ui 节点并同步入站。
- `updateNode(id, formData)`:更新 3x-ui 节点连接信息并重新同步入站。
- `deleteNode(id)`:删除节点及本地关联数据。
- `testNodeConnection(id)`:测试 3x-ui 登录并同步入站。
- `batchTestNodeConnections(formData)`:批量测试并同步节点。
- `updateInboundDisplayName(id, formData)`:修改同步入站的前台展示名称。
- `deleteInbound(id)`:仅删除本地入站镜像,不删除 3x-ui 入站。
- `generateAgentToken(nodeId)`:生成 Agent Token。
- `revokeAgentToken(nodeId)`:撤销 Agent Token。
#### 订阅:`src/actions/admin/subscriptions.ts`
- `suspendSubscription(id)`:暂停订阅,并通过 3x-ui 禁用代理客户端。
- `activateSubscription(id)`:恢复订阅,并通过 3x-ui 启用代理客户端。
- `cancelSubscription(id)`:取消订阅。
- `deleteSubscriptionPermanently(id)`:强制删除订阅及名下关联数据,并尽量删除 3x-ui 客户端。
- `reassignStreamingSlot(...)`:调整流媒体槽位。
- `batchSubscriptionOperation(formData)`:批量处理订阅。
#### 订阅风控:`src/actions/admin/subscription-risk.ts`
- 更新复核状态和复核备注。
- 生成风险报告。
- 向用户发送风险报告并开启用户端全屏限制。
- 解除封控限制并恢复可恢复的代理订阅。
- 保持封禁/暂停并记录最终处理结果。
后台“订阅风控”页面依赖 `src/services/subscription-risk-review.ts` 整理地图、IP、分析日志和报告文本。
#### 订单:`src/actions/admin/orders.ts`
- `confirmOrder(orderId)`:手动确认订单并触发开通。
- `cancelOrder(orderId)`:取消订单。
- `updateOrderReview(...)`:更新风控/复核状态。
- `batchOrderOperation(formData)`:批量操作订单。
#### 其他管理动作
- 用户:`src/actions/admin/users.ts` - 用户:`src/actions/admin/users.ts`
- 套餐:`src/actions/admin/plans.ts` - 套餐:`src/actions/admin/plans.ts`
@@ -200,20 +334,37 @@ Server Actions 是后台和用户端写操作的主要入口。所有管理动
- 流量视图刷新:`src/actions/admin/traffic.ts` - 流量视图刷新:`src/actions/admin/traffic.ts`
- 优惠券与促销:`src/actions/admin/commerce.ts` - 优惠券与促销:`src/actions/admin/commerce.ts`
### 用户端 ### 用户端 Actions
- `src/actions/user/purchase.ts`:立即购买、续费、增流量、查询库存 - `src/actions/user/purchase.ts`:立即购买、续费、增流量、查询库存
- `src/actions/user/cart.ts`:加入购物车、移除、清空、结算 - `src/actions/user/cart.ts`:加入购物车、移除、清空、结算
- `rotateSubscriptionAccess(subscriptionId)`:重置代理订阅访问凭据,并同步更新 3x-ui 客户端 - `rotateSubscriptionAccess(subscriptionId)`:重置代理订阅访问凭据,并同步更新 3x-ui 客户端
- `src/actions/user/account.ts`:资料、密码、邀请码 - `src/actions/user/account.ts`:资料、密码、邀请码、邮箱变更。
- `src/actions/user/notifications.ts`:已读、删除、清空 - `src/actions/user/notifications.ts`:已读、删除、清空
- `src/actions/user/support.ts`:创建、回复、关闭、删除工单 - `src/actions/user/support.ts`:创建、回复、关闭、删除工单。创建工单会受后台工单上限控制。
- `src/actions/user/orders.ts`:取消待支付订单、重新选择支付方式 - `src/actions/user/orders.ts`:取消待支付订单、重新选择支付方式
### 约定 ## 风控数据模型要点
- 写操作必须做权限校验和输入校验 - `SubscriptionAccessLog`:保存订阅 API 访问和节点真实连接证据。
- 重要副作用必须记录审计日志 - `SubscriptionRiskEvent`:保存风控事件、复核状态、报告、用户端限制和最终处理动作。
- 影响页面展示后必须 `revalidatePath` - `SubscriptionRiskReason`:包含城市、省/地区、国家变化,以及节点高频、目标分散等原因。
- 代理客户端变更必须通过 `src/services/node-panel` 同步 3x-ui - `AppConfig`:保存订阅风控总控、自动暂停开关、阈值、节点日志风控阈值。
- 不再新增节点控制面、运行配置下发、进程管理类 Action - `NodeClient.email`:用于匹配 Xray access log 中的 `email:`。它可能形如 `user@example.com-cmojtnp3`,不要手动在 3x-ui 修改。
## 错误处理约定
- 输入校验失败:返回 400 或在 Server Action 中返回可展示错误。
- 未登录:返回 401 或跳转登录。
- 权限不足:返回 403 或抛出权限错误。
- 资源不存在:返回 404 或抛出 not found。
- 外部服务失败:保留审计日志或任务记录,前端展示简洁错误。
- 生产环境 Server Components 会隐藏原始堆栈;排障时看 `docker compose logs -f app`
## 维护约定
- 新增公开 HTTP 接口时,同时更新 `docs/API.md``docs/openapi.yaml`
- 新增 Agent 上报字段时,同时更新 `agent/jboard-agent/README.md`
- 新增系统设置时,同时更新 `.env.example` 或 README 中对应后台配置说明。
- 涉及 3x-ui 客户端状态的写操作必须通过 `src/services/node-panel` 同步。
- 不再新增节点控制面、运行配置下发、Xray 进程管理类 Action。