Files
hy2-panel/README.md
T

238 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# HY2 Panel
单机自托管的 Next 16 管理面板,面向 Hysteria 2 HTTP 鉴权与多节点流量聚合场景。
功能包括:
- 单管理员本地登录,基于 SQLite 持久化会话
- hy2 用户管理:启用/禁用、重置密码、到期时间、总流量上限、稳定 `auth_id`
- 多节点管理:每节点独立鉴权 URL + token、`trafficStats` URL/secret、轮询间隔
- 公开 HTTP 鉴权接口:返回标准 `200 + { ok, id }`
- 后台轮询 `trafficStats`、聚合用户流量、记录同步错误与鉴权审计
- 对禁用、过期、超额用户调用节点 `kick` 做准实时断开
## Environment
复制 `.env.example` 为 `.env`,至少设置:
```bash
APP_URL=http://127.0.0.1:3000
SESSION_SECRET=your-long-random-secret
SESSION_COOKIE_SECURE=auto
ADMIN_PASSWORD=your-strong-admin-password
```
说明:
- `ADMIN_USERNAME` / `ADMIN_PASSWORD` 是单管理员账号,启动时会同步到数据库中的唯一管理员记录
- `SESSION_COOKIE_SECURE=auto` 时会按 `APP_URL` 协议决定是否开启 `Secure` cookie;如果你是直接用 `http://IP:3000` 访问,不要强制设成 `true`
- `DATABASE_PATH` 默认是 `./data/hy2-panel.db`
- `POLLER_ENABLED=true` 时,Next `instrumentation.ts` 会在 Node 进程启动后启动轮询器
## Development
```bash
npm install
npm run dev
```
打开 `http://127.0.0.1:3000`。
## Build
```bash
npm run lint
npm run build
```
这里将生产构建固定为 `next build --webpack`。原因是 Next 16 默认 Turbopack,但在部分受限环境下会触发构建期端口绑定问题;Webpack 构建已验证通过。
## HY2 Node Access
面板里的每个节点都会生成独立鉴权 URL,例如:
```yaml
auth:
type: http
http:
url: http://127.0.0.1:3000/api/hy2/nodes/tokyo-01/auth?token=YOUR_TOKEN
insecure: false
```
根据 Hysteria 官方文档,HTTP 鉴权回调请求体是:
```json
{
"addr": "123.123.123.123:44556",
"auth": "username:password",
"tx": 123456
}
```
面板响应:
```json
{
"ok": true,
"id": "immutable-auth-id"
}
```
多节点识别依赖“不同的 URL 路径”,不是依赖 hy2 自动附带节点 ID。
## trafficStats
节点需启用:
```yaml
trafficStats:
listen: :9999
secret: some_secret
```
面板会轮询:
- `GET /traffic?clear=1`
- `GET /online`
- `GET /dump/streams`
- `POST /kick`
## systemd
已提供示例单元文件 [deploy/hy2-panel.service](/root/hy2-panel/deploy/hy2-panel.service)。
典型流程:
```bash
npm install
npm run build
sudo cp deploy/hy2-panel.service /etc/systemd/system/hy2-panel.service
sudo systemctl daemon-reload
sudo systemctl enable --now hy2-panel
```
## Nginx 反代
已提供示例站点配置 [deploy/nginx-hy2-panel.conf](/root/hy2-panel/deploy/nginx-hy2-panel.conf)。
如果你的公网域名是 `hy2.xn--876a.net`,建议生产环境把 `.env` 中的 `APP_URL` 改成:
```bash
APP_URL=https://hy2.xn--876a.net
SESSION_COOKIE_SECURE=auto
```
示例配置默认反代到 `127.0.0.1:3000`,证书路径为:
```text
/etc/nginx/ssl/hy2.xn--876a.net/fullchain.pem
/etc/nginx/ssl/hy2.xn--876a.net/privkey.pem
```
典型启用流程:
```bash
sudo mkdir -p /etc/nginx/ssl/hy2.xn--876a.net
sudo cp fullchain.pem /etc/nginx/ssl/hy2.xn--876a.net/fullchain.pem
sudo cp privkey.pem /etc/nginx/ssl/hy2.xn--876a.net/privkey.pem
sudo cp deploy/nginx-hy2-panel.conf /etc/nginx/sites-available/hy2-panel.conf
sudo ln -sf /etc/nginx/sites-available/hy2-panel.conf /etc/nginx/sites-enabled/hy2-panel.conf
sudo nginx -t
sudo systemctl reload nginx
```
如果你当前的 hy2 节点仍然直接访问 `http://38.246.237.36:3000/api/hy2/...` 作为鉴权地址,可以继续保留这一入口。上面的 Nginx 只接管 `80/443` 上的域名访问,不会替换或中断现有的 `:3000` 直连。
面板内部生成链接时会优先使用反代传入的 `X-Forwarded-Host` / `X-Forwarded-Proto`,如果是直接访问 `http://38.246.237.36:3000`,则会自动退回到当前请求的 `Host`。
## UI 与交互
界面使用 shadcn/ui(本地组件位于 `components/ui`),以列表、行内展开和中性色分隔线为主。代理组节点排序使用 dnd-kit,支持鼠标、触屏,以及空格开始、方向键移动、空格放下、Escape 取消的键盘操作。修改排序后点击保存,也可撤销。
用户、节点和最近 100 条审计记录支持本页即时搜索和状态筛选。用户、节点与模板表单支持 Ctrl/Cmd + Enter 提交,保存失败会保留输入;删除操作通过确认对话框执行。
运行浏览器回归:
```bash
npx playwright install chromium
npm run test:e2e
```
测试自动启动 3106 端口的开发服务,使用 `/tmp` 中独立的临时数据库并关闭节点轮询,不访问现有数据库。覆盖排序持久化、鼠标/键盘/模拟触屏、列表筛选、用户编辑、复制链接、删除确认、失败保留输入和移动端溢出检查。截图输出在 `test-results/`。运行前请停止同一工作目录的其他 Next 开发服务。
## 自定义订阅节点与数据库兼容
在「节点管理 → 新增自定义订阅节点」填写显示名、Slug 和单个 Clash/Mihomo proxy 的 YAML。支持单对象、单节点列表,以及 `proxies:` 包装。协议参数(例如 AnyTLS 的 password、sni、alpn)由 YAML 提供;订阅名使用 YAML `name`,面板显示名独立。原始 YAML 和注释按原样保存,输出订阅时才解析、序列化。格式错误会在表单内提示并保留输入。
自定义节点与 HY2 节点共用列表、启停、删除、主组拖拽排序及自定义分组。自定义节点仅分发配置,不参与 HY2 HTTP 鉴权、轮询或面板流量计量,也不生成 HY2 服务端配置。代理的访问控制和流量限制由该代理服务自身负责。
数据库升级沿用服务器现有的 **SQLite `user_version = 4`**,保留 `hy2_nodes.node_type`(默认 `hy2`)和 `hy2_nodes.custom_config_yaml`(默认空字符串)的原名称、类型和默认值:
- 全新数据库、版本 1–3 的数据库在启动时自动迁移。
- 服务器已有的完整版本 4 不再重复添加列,也不重写现有记录。
- 对于版本 3/4 中已部分添加的自定义节点字段,只补充缺失列。
- 迁移在一个 SQLite 写事务中执行,失败回滚;更高版本的数据库会拒绝启动,避免错误降级。
- 节点 ID、用户 ID、订阅 token、加密凭据、额度、会话、历史流量和代理分组 JSON 都不因迁移而重建。
升级时保留原 `.env`、`DATABASE_PATH`、`SESSION_SECRET` 和管理员配置。尤其不能更换 `SESSION_SECRET`,现有 HY2 用户凭据依赖它解密。发布前应停服务并通过 SQLite backup API 备份数据库(包含 WAL 中已提交的数据),不要仅复制正在写入的 `.db` 文件。随后更新代码、安装锁定依赖、构建并启动;无需导出导入业务数据,也无需手工执行 `ALTER TABLE`。
`tests/fixtures/remote-v4-schema.sql` 是从服务器只读获取的实际表结构,不含生产数据。`npm test` 使用该结构和模拟业务数据验证兼容性、重复迁移、失败回滚、原始 YAML 保留、订阅生成,以及自定义节点不参与鉴权和轮询。`npm run test:e2e` 验证新版 UI 的新增、校验、编辑、分组、禁用和删除流程。
## 证书托管与服务器自动安装
管理员进入「证书与安装」,上传 PEM 完整证书链(CRT)和未加密私钥(KEY)。证书私钥使用 `SESSION_SECRET` 派生密钥加密保存,不在页面回显;请保留原有 `SESSION_SECRET` 并备份数据库。本功能使用覆盖 `*.p.xn--876a.net` 的通配符证书;只管理上传的证书,不申请或自动续期,也不会自动更新已安装服务器的文件。
选择证书、填写节点名称与 Slug,生成并下载安装脚本。每份脚本限一个节点,有效期 24 小时,可在平台撤销。脚本不内嵌证书私钥,运行时通过 HTTPS 获取配置和证书,安装完成后凭据不能再次获取私钥。
在使用 systemd 的 Linux 服务器上以 root 运行(支持 x86_64、ARM64、ARMv7):
```bash
sudo bash install-jp1.sh
# 或显式指定参数;jp1 可替换为任意合法的单级子域名前缀:
sudo bash install-jp1.sh --domain jp1 --hy2-port 23456 --stats-port 23457
# NAT 内外端口不同:
sudo bash install-jp1.sh --domain jp1.p.xn--876a.net \
--hy2-port 23456 --stats-port 23457 \
--hy2-listen-port 443 --stats-listen-port 9999
```
无参数时交互输入域名和两个端口。短域名自动补全 `.p.xn--876a.net`;完整域名用作订阅地址和 SNI。请提前将域名解析至服务器公网 IP,在 NAT / 云防火墙设置 UDP 的 HY2 映射和 TCP 的统计 API 映射。脚本不能代替云厂商配置端口转发或 DNS。统计 API 使用随机密钥,建议将其 TCP 端口限制为仅面板 IP 可访问。
脚本安装 curl/jq/openssl 等依赖,从 Hysteria 官方下载入口下载服务端,保存 `/etc/hysteria/config.yaml`、`server.crt`、`server.key`,创建 `hy2-panel-node.service` 并设置开机启动。先以禁用状态注册,检查本机统计 API 健康后启用节点。公网 NAT 连通性请通过平台的节点同步状态确认。
重复执行仅允许同一安装记录、同一域名和端口,不覆盖其他已有 HY2 配置。失败后修复问题,在凭据有效期内重试;已启用的节点不因删除安装记录而删除。凭据过期且已有部分安装时,请先检查并清理对应的禁用节点和服务器配置,再生成新的安装记录。
平台 `APP_URL` 必须是服务器能访问的公网 HTTPS 地址(本地测试允许 localhost HTTP)。新迁移使用数据库版本 5,只新增 `managed_certificates` / `node_installations` 表,兼容现有 v4 节点、用户和订阅数据。部署前仍应备份数据库;不要用旧版本程序打开已升级的数据库。
## 托管 AnyTLS / sing-box
「证书与安装」选择 **AnyTLS · TCP / sing-box**,下载脚本后运行:
```bash
sudo bash install-jp2-anytls.sh --domain jp2 --port 51046 --listen-port 51046
```
只需映射代理 TCP 端口。sing-box 与管理程序使用独立目录和 systemd 单元,不覆盖已有 HY2。管理 API 自动分配本机端口,节点每 15 秒通过 HTTPS 主动向面板同步,无需开放公网管理端口。支持 Debian/Ubuntu、dnf 系发行版的 x86_64 / ARM64。
- 每用户派生独立的 AnyTLS 密码,订阅自动生成对应节点。更改用户密码会更新 AnyTLS 凭据。
- 用户禁用、到期、额度耗尽及节点禁用在下次同步时生效。当前通过重启 sing-box 应用配置,所有已有连接会断开;配额为周期检查,可能产生一个同步周期的超额。
- 连续无法同步超过 90 秒,或本地已到租约到期时间时停止代理;重新连接面板后自动恢复。管理程序异常退出也会停止代理。
- 从 V2Ray API 读取累计用户流量,以进程启动标识和累计值去重;待发送报告落盘,网络重试不重复计费。流量为应用层统计,异常掉电/崩溃可能丢失最后一次采样之后的数据,不能当作精确的计费凭证。在线用户数暂不展示,连接数来自 Clash API。
- 数据库迁移 v6 只增加安装协议字段和累计采样表,原 HY2 / 自定义节点保持兼容。
官方 sing-box 默认发行包未启用 `with_v2ray_api`。部署面板前运行 `bash scripts/build-sing-box.sh`,构建**未经修改的** sing-box v1.14.2(固定源码 commit `af6e64c3b69e6132ebaee0e1a3d24e93903f6709`),启用 `with_v2ray_api,with_clash_api,with_utls`。需要 Go 1.25.5 或更新版本。将生成的 `data/artifacts/` 作为部署产物保存到面板同一路径;程序不会把二进制或任何凭据提交到 Git。安装脚本从面板 HTTPS 下载二进制并核对 SHA-256;没有产物时下载端点返回 503。
上游源码与许可:https://github.com/SagerNet/sing-box/tree/v1.14.2 ,GPL-3.0-or-later。`lib/templates/stats.proto` 来自该版本,许可说明见同目录 `sing-box-LICENSE`。构建脚本提供可复现的源码获取与编译步骤。
真实协议回归可运行:`SING_BOX_TEST_BINARY=/path/to/sing-box AGENT_TEST_PYTHON=/path/to/python npx tsx tests/anytls-runtime.ts`(Python 环境需 grpcio 和 grpcio-tools)。它验证 TLS 校验、实际转发、按用户统计及停用后的拒绝连接。
## 中转主机与线路
「中转线路」新增入口主机,下载安装 SH,以 root 在该主机运行。脚本安装固定版本 Realm v2.9.6(官方 Linux musl x86_64 / ARM64 产物,内置 SHA-256),独立使用 `/etc/hy2-panel-relay`、`/usr/local/lib/hy2-panel-relay`、`hy2-panel-relay.service` 和 `hy2-panel-relay-agent.service`。不覆盖已有代理服务,不自动修改防火墙;需放行选定的监听端口,并配置云防火墙/NAT 公网端口映射。脚本含长期管理凭据,应按密钥保管;删除主机可撤销凭据。
新增线路时选择入口主机、原目标节点,填写公网端口与本机端口。第一版支持托管 HY2(UDP)和 AnyTLS(TCP),保留原节点直连。入口只转发加密流量,不持有节点证书、私钥或用户密码;订阅地址切换到入口,但 SNI 保留原目标域名。AnyTLS 仍允许在 TCP 隧道内转发 UDP 业务。
管理程序每 15 秒主动获取配置,检查本机端口冲突及 Realm 实际监听情况,配置变更会重启这一台主机的 Realm 并断开已有中转连接。启用、停用、删除在下次同步生效;无法联系平台约 90 秒后停止转发,联网后恢复。页面显示配置/进程状态,不能代替真实协议或大陆线路质量测试。UDP 空闲映射保留 300 秒。
仅最近上报、配置已应用且服务运行的线路进入订阅,可复用订阅拖拽排序和分组。目标节点停用时其中转线路也停止发布并从转发配置移除。数据库 v7 仅新增 `relay_hosts`、`relay_routes`,中转线路不会插入 `hy2_nodes` 或参与节点轮询;用户流量仅由落地节点计量一次,第一版不区分同一用户的直连/中转用量。删除被引用的目标节点前需先删除对应线路。