import { createHmac } from "node:crypto"; import { decryptText } from "@/lib/crypto"; import { getEnv } from "@/lib/env"; import type { Hy2UserRow, Hy2NodeRow } from "@/lib/store"; export const SING_BOX_VERSION = "1.14.2"; export function anytlsPassword( user: Pick, ) { const secret = decryptText(user.auth_secret_encrypted); if (!secret) throw new Error("user_secret_unavailable"); return createHmac("sha256", getEnv().SESSION_SECRET) .update(`anytls\0${user.auth_id}\0${secret}`) .digest("base64url"); } export function buildSingBoxConfig(node: Hy2NodeRow, users: Hy2UserRow[]) { return { log: { level: "warn", timestamp: true }, inbounds: [ { type: "anytls", tag: "anytls-in", listen: "::", listen_port: Number(node.hy2_listen.replace(/^:/, "")), users: users.map((u) => ({ name: u.auth_id, password: anytlsPassword(u), })), tls: { enabled: true, certificate_path: "/etc/hy2-panel-anytls/server.crt", key_path: "/etc/hy2-panel-anytls/server.key", }, }, ], outbounds: [{ type: "direct", tag: "direct" }], experimental: { v2ray_api: { listen: node.traffic_stats_listen, stats: { enabled: true, users: users.map((u) => u.auth_id) }, }, clash_api: { external_controller: new URL(node.traffic_stats_url).host, secret: node.traffic_stats_secret, }, }, }; }