Skip to content

安全加固

状态:Roadmap

最后核对:2026-05-15

本文记录证书 pin、本地配置持久化、密钥驻留、rekey 策略、Noise 首包行为和 REALITY 密钥轮换相关的安全加固路线。

当前状态

领域状态当前行为
上游 TLS SPKI pin完成TCP upstream TLS 规则携带 upstream_tls_spki_pins_sha256。Agent 对叶子证书 SPKI DER 计算 SHA-256 并比对 pin;启用 upstream TLS 但没有 pin 的规则会被拒绝。
Agent 本地配置 cache已移除Agent 不再读写本地配置 cache 文件。已应用的 L4/L3 配置只保留在进程内存中;重启后由控制面重新下发。
Secret zeroization完成 + 规划控制 PSK decode buffer、生成的 PSK 和控制通道临时私钥已使用 Zeroizing。全 runtime secret wrapper 覆盖仍是规划。
Secret logging完成runtime fingerprint 不再包含私钥原文 hex;需要稳定标识时使用短 SHA-256 标识。
控制通道 rekey完成Agent 会在 NEXUS_CONTROL_REKEY_INTERVAL_SECS 后重连 secure control session,默认 6 小时。
QUIC 重连周期完成QUIC REALITY client 会在 NEXUS_QUIC_MAX_CONNECTION_AGE_SECS 后关闭旧连接并重连,默认 6 小时。
Noise 首包 payload完成Noise handshake message 不再携带业务 payload。首个业务 payload 会排队,等 transport key 生成后再发送。
REALITY 双 profile 轮换规划当前 runtime 会拒绝同一个 UDP listener 上的 QUIC REALITY route 混用不同 private key,并提示使用 dual profile/epoch 轮换。完整 active/next/retiring 生命周期尚未实现。

安全目标

当前加固切片目标是:

  • 不在本地磁盘创建控制面 L4/L3 配置副本。
  • 只要 Agent 进程还活着,控制面断开后已应用的数据面 listener 继续从内存状态运行。
  • Agent 重启后必须等待控制面权威 replay,不信任本地 last-known-good cache。
  • 为未来审计“本地已应用配置”和“后端期望配置”的差异提供 apply 信号。
  • 普通业务 upstream TLS 不再使用 no-verify,而是使用显式 SPKI pin。
  • Noise 首个 handshake packet 不携带业务 payload。

它不承诺防御已经获得运行时最高权限的攻击者。如果攻击者能读取进程内存、 ptrace、抓 core dump,Zeroizing 只能缩短暴露窗口,不能保证“内存里一无所获”。

SPKI Pin

TcpProxyRule 包含:

protobuf
repeated string upstream_tls_spki_pins_sha256 = 20;

支持 hex、base64 或 base64url 编码,内容是:

text
SHA-256(subjectPublicKeyInfo DER)

规则:

  • upstream TLS 必须至少有一个 pin。
  • 可以配置多个 pin,用于证书或密钥轮换。
  • pin 必须显式配置;默认不做 TOFU。
  • REALITY camouflage target 探测可以保留 probe-only no-verify 路径,但普通 upstream TLS 不可以。

已移除本地配置 Cache

之前的 Agent 磁盘 cache 已移除。Agent 不再创建、加载、迁移或更新:

  • agent-state.nxc
  • agent-state.previous.nxc
  • agent-state.json

这些 cache 环境变量不再属于运行时契约:

  • NEXUS_CACHE_DIR
  • NEXUS_AGENT_CACHE_KEY
  • NEXUS_AGENT_CACHE_KEY_FILE
  • NEXUS_AGENT_CACHE_ALLOW_INSECURE_KEY_FILE

当前运行语义:

  • 如果配置已经应用,之后控制面断开,现有 forwarder 和 L3 tunnel 继续使用内存状态运行。
  • 如果 Agent 进程重启且 backend 不可用,本地不会应用任何旧配置;Agent 会重连并等待控制面权威 replay。
  • 可以在进程内用 hash/bytes 跳过重复配置,但这些状态不落盘。

理由:如果没有硬件背书、运维持有或外部 secret,本地 cache 加密不能解决离线磁盘泄露。 不保存本地配置 cache 更简单、更容易审计,也把恢复边界明确放在 backend 可用性/HA 上。

Rekey 和前向安全

Secure control session 使用认证的 open-session 交换和 AEAD frame。Agent 会按配置周期主动重连,重新派生 session key。

Noise UDP 行为刻意向 WireGuard 的安全模型靠拢:

  • handshake packet 不携带任意业务 payload。
  • 首个业务 payload 在本地排队。
  • 只有 transport key 派生完成后才发送业务 payload。

这样仍能保持较快的用户感知路径,同时避免把应用数据塞进首次 handshake message 带来的弱前向安全语义。

QUIC REALITY 当前以连接生命周期作为 rekey 边界。如果未来 QUIC 库暴露显式 key update 接口,可以进一步接入;目前使用 reconnect。

REALITY 轮换

当前同端口 QUIC REALITY 凭据约束:

  • 同一个 UDP listen address 上的 QUIC REALITY route 必须使用同一个 REALITY private key。
  • 不同 SNI/shortId 可以在该 key 边界内共享 QUIC REALITY listener。
  • 同 listener 上的 QUIC REALITY route 混用不同 REALITY private key 会被拒绝。
  • 这个凭据边界不阻止同一个 UDP socket 同时承载 UDP RAW fallback 或 UDP Noise route,只要包分发信号明确。

规划中的完整轮换模型:

  • REALITY profile 存储 activenextretiring 状态。
  • 先部署 dual-accept profile set。
  • 客户端逐步切换到 next public key 和 shortId。
  • telemetry 显示旧 key 使用清空后,再 retire old profile。
  • 审计 profile epoch、public-key fingerprint、节点应用状态和仍使用旧 key 的连接数。

剩余工作

  • 在 protobuf/database 边界之后,把更多运行时 Vec<u8>/[u8; 32] 私钥载体替换为 secret newtype。
  • 为 config update 增加 backend Ed25519 签名校验。
  • 增加 SPKI pin 管理 API 和 UI。
  • 实现完整 REALITY active/next/retiring credential 生命周期。
  • 将 pin failure、config replay/apply event、rekey event、REALITY rotation event 接入监控矩阵和 TimeDB pipeline。

NexusNet documentation