Files
NexusGate/NEXT-ROUND-REPORT-V4.md
T
aaaamoooo 5cfc5bebd7
CI / test (push) Waiting to run
CI / anytls-smoke (push) Waiting to run
docs(v4): batch report for items 24/25 + notes entries as authored
2026-10-21 13:45:15 +00:00

5.3 KiB
Raw Blame History

amo v4 批报告(第 24、25 条)

  • 基线:18074da(开工核对一致)
  • 提交:408b03e(第 25 条)、1e7ccd3(第 24 条),文档收尾提交随本报告
  • 范围口径:第 0 条 Go 单一真源——只改 panel-go/、agent-go/、共用前端 public/,Node 零改动
  • 状态:第 25 条完成、第 24 条完成(完成状态只在此报告标注,NEXT-ROUND-NOTES 原文未删改,随本批一并提交)
  • 未部署、未推 Gitea

第 25 条 agent 鉴权令牌化(提交 408b03e)

设计

  • 签发:agent 请求先按原路径鉴权——指纹(KeyFingerprint)定位记录后 VerifySecret 跑 scrypt——通过后才签发会话令牌。令牌为 RandomToken(40),与 agent 密钥同一强度;每次密钥路径鉴权成功都会轮换签发新令牌(旧令牌即刻失效)。
  • 存储(面板):agent 记录只存令牌的 SHA-256 哈希(SessionTokenHash,复用 TokenFingerprint)与过期时间(SessionTokenExpiresAt),明文不落库。两字段 omitempty,旧数据文件零迁移。
  • 有效期:24 小时。经响应头 X-Agent-Session-Token / X-Agent-Session-Token-Expires 下发。
  • 校验:后续请求带令牌作 bearer,面板走 agentBySessionToken()——store.View 内扫描、hex 解码后 subtle.ConstantTimeCompare 常时比对、校验记录 active 与过期时间。不再跑 scrypt。
  • 回退:令牌过期/哈希不符/记录吊销 → 该请求自动回退密钥路径(scrypt),成功后重签新令牌。agent 侧:收到 401 且本次用的是令牌时,清掉本地令牌、以密钥重试恰好一次(防循环);面板未签发(旧面板)时不写令牌文件、逐请求带密钥,行为与旧版一致。
  • 吊销语义:(*Agent).Revoke() 统一收口——置 revoked 并清空令牌两字段。三处调用:重新 enroll 时吊销同服务器旧 agent、delete_server、force_forget_server。全仓 "revoked" 字面量只剩 Revoke 内部一处,不存在遗漏的失效路径(agent 密钥本身从不在原记录上重置,重置只经重新 enroll 建新记录 + 吊销旧记录)。
  • 存储(agent):session-token.json 放在既有状态目录(默认 /etc/nexusgate/agent,可经 NG_SESSION_TOKEN_FILE 覆盖),权限 0600、临时文件 + rename 原子落盘,与 keys.json 同规格。读取时带 1 分钟过期余量,过期直接用密钥。
  • 强度不降级:签发必须在 scrypt 验证通过之后;库里始终只有哈希(密钥哈希 + 令牌哈希);令牌绑定单条 agent 记录。
  • 兼容:旧 agent 不带令牌 → 继续逐请求 scrypt,功能不受影响;新 agent 连旧面板 → 无签发头,自动回退。agent 版本号保持 0.6.8。线格式不变,差异已登记 agent-go/PARITY.md 第 0 条。

改动点

面板(panel-go):

  • types.go:Agent 新增 SessionTokenHash / SessionTokenExpiresAt(omitempty);新增 (*Agent).Revoke()。
  • handlers.go:AgentSessionTokenTTL = 24h;agentBySessionToken()、issueAgentSessionToken()(Transaction 落盘、记录已非 active 则不签发)、authenticateAgent()(令牌路径 → 密钥路径;候选记录先从 View 拷出、scrypt 在锁外执行、成功后签发);FindAgentByBearer 保留为兼容 wrapper;handleAgent 在签发时设置两响应头;三处吊销改走 Revoke()。
  • 新增 agenttoken_test.go:7 例(签发且只存哈希、篡改 KeyHash 后令牌仍可鉴权即令牌路径不跑 scrypt、过期被拒 + 密钥重签轮换、哈希不符被拒 + 重签、吊销后令牌与密钥双拒、令牌绑定本记录、纯密钥请求逐次轮换可用)。

agent(agent-go):

  • main.go:SessionTokenFile 配置(env NG_SESSION_TOKEN_FILE);agentSessionToken + 懒加载状态(mutex);currentSessionToken()(1 分钟余量)、storeSessionToken()(0600 + rename)、clearSessionToken();request() 拆为 requestAttempt(bearer 优先令牌、每响应检查签发头并落盘、401 用令牌时清令牌以密钥重试一次)。
  • 新增 sessiontoken_test.go:5 例(fakePanel:捕获/落盘 0600/冷启重载/复用、401 回退 + 重签、旧面板无头时纯密钥、客户端已过期直接用密钥、令牌与密钥双拒时报错且恰好两次尝试)。

验收 ①:稳态 CPU(按 v3 同一测法复测)

测法:20 服务器种子(20 台 enrolled agent、40 节点、40 客户、约 160 绑定,数据文件 196KB,与现网 225KB 同量级);令牌感知驱动按现网节奏模拟 20 台 agent(poll 8s / heartbeat 30s / usage 60s、空 samples、错峰),无界面请求;预热 15s 后取 60s 窗口,按 /proc/<pid>/stat 的 utime+stime 差折算(100 ticks = 1 秒 CPU),同一台架、同一脚本、面板进程为脚本直系子进程采样。

二进制 稳态 CPU(单核 %) 驱动侧证据
旧 18074da(本机同台架实测) 28.98% 未签发令牌;请求延迟 74–254ms
新 v4(HEAD) 1.52% 恰好签发 20 个令牌、20/20 agent 转令牌路径;请求延迟 5–8ms;失败 0
  • v3 报告的旧版数字为 32.31%(其台架种子构成略有差异),本批同台架复跑为 28.98%,量级一致;新版 **1 ...[truncated 6135 chars]