架构与安全¶
组件¶
┌────────────────────────────────────┐
Admin browser ───────▶│ Panel │
│ Vue SPA (embedded in binary) │
Subscription ────────▶│ REST API + subscription renderer │
│ WebSocket Hub │
Hy2 auth callback ───▶│ SQLite / optional Redis │
└───────────────┬────────────────────┘
│ WSS /api/node/ws
┌───────────────▼────────────────────┐
│ Node Agent │
│ config writer / cert installer │
│ log batcher / stats poller │
└───────┬──────────────────┬─────────┘
│ process │ docker sibling
┌───────▼──────┐ ┌───────▼──────────┐
│ Hysteria 2 │ │ Hysteria / Xray │
└──────────────┘ └──────────────────┘
面板是唯一控制面,节点是数据面。代理核心不直接访问数据库,只通过 Agent 接收配置和上报数据。
配置流¶
节点设置保存
→ 渲染 YAML/JSON,计算 hash
→ hash 未变化则复用 revision
→ 在线 Agent:通过 WebSocket 推送
→ Agent 原子写配置
→ 端口跳跃 / 统计 / 证书准备
→ 重启代理核心
→ config.ack(revision + 错误)
→ 面板记录 appliedRevision / configError
Agent 断线重连时:
- 发送
hello(版本、能力、证书指纹); - 面板补推证书(managed 模式);
- 面板强制同步一次配置;
- Agent 比较 revision 与本地配置,相同且进程运行则直接 ack,不重启。
Agent 协议¶
Agent → 面板¶
| 消息 | 内容 |
|---|---|
hello |
版本、OS、架构、代理版本、能力、证书指纹 |
heartbeat |
CPU/内存/磁盘/load/uptime/在线数/累计流量 |
logs |
日志批次 + batch id |
stats |
用户流量增量 + batch id |
config.ack |
revision、成功/失败、pending |
command.ack |
start/stop/restart 结果 |
cert.request |
CSR、域名、公钥指纹 |
面板 → Agent¶
| 消息 | 内容 |
|---|---|
config |
YAML/JSON、revision、TLS 模式、域名、端口、端口跳跃 |
command |
start / stop / restart |
cert.push |
证书链、指纹、有效期;上传模式含私钥 |
cert.error |
签发失败原因 |
cert.renew |
管理员触发续期 |
log.ack / stats.ack |
幂等确认 |
日志和统计使用 batch id,服务端以 (node_id, batch_id) 唯一索引保证只应用一次;Agent 未收到 ack 会重发。
数据模型¶
主要表:
| 表 | 用途 |
|---|---|
admins |
管理员、密码哈希、TOTP 密钥与恢复码 |
users |
代理用户、订阅 Token、流量、到期、设备数 |
groups / user_groups / node_groups |
分组与可见性 |
nodes |
节点设置、Token 哈希、状态、证书元数据 |
node_configs |
配置 revision、YAML、hash、应用结果 |
certificates / node_certificates |
证书、节点映射、指纹与有效期 |
node_metrics |
心跳指标 |
events |
节点上下线、配置、证书、备份等事件 |
hy2_logs |
解析后的代理日志 |
log_batches / stats_batches |
幂等批次 |
api_keys |
作用域、限流、过期 |
settings |
面板设置、加密后的 DNS 凭据 |
acme_accounts |
持久化 ACME 账户密钥 |
SQLite 使用 WAL 模式;VACUUM INTO 生成一致性备份快照。
安全边界¶
面板¶
- 管理员密码使用 bcrypt;
- JWT HS256,密钥为
jwt.secret或JWT_SECRET; - 登录失败按 IP 限流;2FA challenge 一次性、5 分钟有效;
- API Key 只存 SHA-256 哈希,带作用域与独立限流;
- 敏感数据加密:证书私钥、DNS 凭据、TOTP 密钥使用 AES-256-GCM(
cert.key)。
节点¶
- 节点 Token 只存哈希;重置后旧 Agent 失效;
- Agent 只接受面板的配置/命令,不开放入站管理端口;
- 私钥默认不出节点(CSR 模式);
- 端口跳跃需要
NET_ADMIN; - Docker 运行时挂载
/var/run/docker.sock,视为 root 等价权限。
传输¶
- 生产环境必须使用 HTTPS/WSS;
- 自签名面板可在 Agent 设置
PANEL_INSECURE=true,但不建议长期使用; - 反向代理必须支持 WebSocket Upgrade;
- ACME DNS-01 只产生面板到 DNS/CA 的出站连接。
部署模式¶
| 模式 | 说明 |
|---|---|
| 单面板 + 远程节点 | 最常见;节点通过公网 WebSocket 连接 |
| 面板与节点同机 | 节点仍通过面板公开地址连接,便于统一管理 |
| 节点单容器 | Agent 与 Hysteria/Xray 同一容器,HY2_RUNTIME=process |
| 节点 Docker 运行时 | Agent 通过 docker.sock 启动兄弟代理容器 |
失败与恢复¶
| 场景 | 行为 |
|---|---|
| 面板重启 | 管理员会话通常保留(JWT secret / Redis 未变);节点自动重连并补推 |
| 节点断线 | 代理继续按本地配置运行;面板标记离线并记录事件 |
| 配置被拒绝 | 面板记录错误;Agent 回滚旧配置并重启 |
| 证书续期失败 | 旧证书继续服务;到期前定时重试 |
| 面板离线 | 节点继续运行;managed 证书无法续期 |
| 数据库损坏 | 从 backups/ 恢复;原库保留为 pre-restore |