NSIO Docs
NSIO Docs
首页
总体架构

NSN · 站点节点

NSN · 站点节点
NSN · 架构与功能设计
NSN · 演进路线与开发计划

NSC · 用户客户端

NSC · 用户客户端
NSC · 架构与功能设计
NSC · 演进路线与开发计划

NSD · 控制中心

NSD · 控制中心
NSD · 架构与功能设计
NSD · 演进路线与开发计划

NSGW · 数据网关

NSGW · 数据网关
NSGW · 架构与功能设计
NSGW · WireGuard Peer Relay 协议层
NSGW · 演进路线与开发计划

Last Updated: 2026/5/8 08:44:39

Previous Page首页
Next PageNSN · 站点节点

#总体架构

本页给出 NSIO 四组件的"角色 + 互联"总体视图:每个组件在哪个平面、对外暴露什么、谁向谁发起连接、典型时序如何展开、各组件失败时影响范围。组件内部模块见对应组件目录的 architecture.md。

#1. 三平面与组件映射

NSIO 把传统 VPN "认证 + 控制 + 数据转发"混合的网关拆为四个独立组件,归属三个平面:

平面职责谁在这个平面是否承载业务流量
管理面管理员编辑、IdP 对接、审计NSD(Web UI / Admin API)否
控制面身份签发、策略编排、配置分发NSD(唯一来源);NSN / NSGW / NSC(订阅者)否
数据面业务流量转发与 ACL 终决NSGW(中继);NSN(终结 + 终决);NSC(出站封装)是

NSD 是唯一有状态强一致组件,但永不承载业务流量;其余三方都是控制面订阅者,同时是数据面参与者。

#2. 组件互联矩阵(连边视角)

横向是发起方,纵向是接受方;空格表示无直接连接。

↓ 接受 \ 发起 →NSDNSGWNSNNSC浏览器 / 标准工具
NSD—REST 注册 / 端点上报 + SSEREST 注册 / 心跳 / 服务上报 + SSE / Noise / QUICREST 注册 / 心跳 + SSE—
NSGW———WireGuard UDP / WSS(出站)HTTPS 443
NSN—WireGuard UDP / WSS(NSC↔NSN 段 2)———
NSC————127.127.x.x:port / *.n.ns / HTTP 代理

三条不变量:

  • 控制面只发不收:NSD 不主动连接任何节点,所有通道由数据面节点向 NSD 主动拨号。NSGW 同样被动,不主动心跳。
  • 数据面双跳互不耦合:NSC ↔ NSGW 与 NSGW ↔ NSN 是两段独立握手;终结模式下 NSGW 持私钥并解密,中继模式下 NSGW 只见密文。
  • NSD 永不持有私钥:下发结构(如 WgConfig)协议级地不含 private_key 字段。

#3. 拓扑与基数

NSIO topology

  • NSD : NSGW : NSN : NSC = M : N : X : Y,其中 M 通常为少量(云端 + 私有 NSD 共存),N 按 PoP / region 扩展,X / Y 由租户规模决定。
  • 多 NSD 并行是一等公民:同一台 NSN / NSC 可同时归属多个 NSD,合并发生在节点侧(MultiControlPlane),NSD 之间互不感知,不联邦同步。
  • NSGW 之间互不感知:选路决策放在 NSC / NSN 的多网关管理器里,网关侧无需维护"全局选路状态"。

#4. 控制面下发:注册 → 订阅 → 推送

四个组件的启动顺序、事件订阅子集与触发源:

NSIO bootstrap and SSE fanout

按订阅者类型选择事件子集,事件签名独立于外层传输(SSE / Noise IK / QUIC 共用同一事件解析器):

事件类NSNNSGWNSC
wg_config(WireGuard 拓扑)✓✓接收点已就位、未消费
proxy_config / acl_config✓—接收点已就位、未消费
acl_projection(预拒副本)—✓—
gateway_config(网关拓扑)✓—✓
routing_config✓✓✓
dns_config✓—✓
services_ack✓——
token_refresh / ping / pong✓✓✓

NSD 推送的触发源:订阅建立、services/report 与 gateway/report 上报触发、管理员变更、JWT 临近过期。

#5. 数据流向

时序图(§5.1 / §5.2)回答"消息按时间如何往返",本节的两张总图回答"业务数据在路径上的形态变化"与"控制面配置如何驱动数据面行为"——前者是业务数据流,后者是配置数据流。

#5.0 业务数据端到端流向

下图把五种连接形态(§5.4 的 direct / relay / terminate / wss 四模式 + 公网浏览器 https)合并到一张图,用颜色标注加密边界,用节点内文字标注处理逻辑。读图顺序:左侧入口 → 中间封装与处理 → 右侧业务服务出口。

NSIO data flow

模式NSGW 角色加密段数NSGW 是否见明文适用场景
direct不参与1(端到端)—NSC ↔ NSN P2P 可达
relay不解密 UDP 中继1(端到端)✗NAT 阻断直连但 UDP 仍通;managed / 云端 NSGW 的默认(结构性不可观测客户明文,见 §6.4.1)
terminate持私钥并终结2(段 1 + 段 2 独立)✓self-hosted NSGW 的默认;NSGW 也是 ACL 预拒点(managed 形态须客户显式 opt-in,见 §6.4.1)
wss帧缝合(不解 WG)2部分(WSS 内可见)UDP 完全被阻断
httpsTLS 终结 + Host 路由(可选外部鉴权)1(TLS) + 1(段 2 WG)✓不依赖 NSC 的独立公网流量承载:浏览器、API 客户端、移动端、第三方系统等任意公网 HTTPS 客户端,可选挂接外部鉴权(OIDC / mTLS / API key / 签名 URL / Basic Auth)

加密边界三条不变量:

  • 私钥不出节点——direct / relay 下 NSGW 物理上无法读取应用层;terminate 下 NSGW 与 NSN 各自用本地私钥握手,私钥都不来自 NSD。
  • 段 1 与段 2 永远独立——即便都是 WG,NSC↔NSGW 与 NSGW↔NSN 是两次独立握手,terminate 模式下 NSGW 短暂持有明文。
  • NSN 是唯一终决点——所有模式最后都汇到 NSN 的 ACL 引擎,本地服务白名单是不可绕过的最终防线。

#5.1 控制面配置如何驱动数据面

NSD 的 11 类 SSE 事件按订阅者类型分包推送,落在每个数据面节点内部不同的"消费模块"上。下图展示事件 → 模块的驱动关系,以及上报触发推送的反向链路:

NSIO config flow

要点:

  • NSC 已就位但未消费:wg_config / proxy_config / acl_config 三类事件 NSC 端已定义接收点(虚线),但当前实现忽略;预留给未来 TUN 模式、出站 ACL 预检等能力。
  • 上报驱动合成:NSN 的 services/report 与 NSGW 的 gateway/report 是触发 NSD 策略合成的关键反向链路;管理员只编辑高层意图(ACL / 角色),低层配置(路由、DNS、WG 拓扑)由 NSD 据上报自动展开。
  • gateway_wg_relay 是 relay 模式的载体:NSD 在为某条 (NSC, NSN) 边选定 relay 模式时,下发的不是探测指令,而是直接 materialize 出"中继配对表"给对应 NSGW,配合双方的 wg_config 一次性激活。

#6. 时序细节:双跳与浏览器直达

#6.1 NSC 用户:双跳

用户进程在本机连 127.127.x.x:port 或 *.n.ns,经由 NSC 的 VIP 监听器 / HTTP 代理出站,经 NSGW 中继送达目标 NSN:

NSC data path

关键点:

  • 段 1 与段 2 加密独立。终结模式下 NSGW 解密重封并触发 /client 入口预拒;不解密中继模式下 NSGW 不参与握手,NSC ↔ NSN 端到端加密。
  • ACL 两层信任:NSGW 偏宽(fail-open)+ NSN 偏严(fail-closed,本地白名单兜底)。
  • 代理即 NAT:NSN 不重写 IP 头,只做端口到服务的查找;conntrack 维护反向回包。

#6.2 公网入口:NSGW 独立流量承载

不依赖 NSC 的公网 HTTPS 客户端(浏览器、API 客户端、移动端、第三方系统)通过 NSGW 的 443 入口直达 NSN 上的服务。这是 NSGW 在"无 NSC 部署"形态下的主入口,与 §6.1 的 NSC 双跳并列:

HTTPS direct path

关键点:

  • TLS 在 NSGW 终结,依据 Host / SNI 选 NSN 路由(routing_config)。
  • 边界身份认证 vs 服务级授权分层:NSGW 不读 HTTP 路径、不重写业务头、不做服务级授权;但可选挂接外部鉴权(OIDC / mTLS / API key / 签名 URL / Basic Auth)确认访问主体(详见 nsgw/architecture.md §2.4.1),主体以 NSGW 签名头部透传给 NSN。
  • 段 2 仍走 WireGuard 隧道,授权裁决由 NSN 终决(ACL 终结点 + services.toml 兜底)。

#6.3 第三条路径:WireGuard 不解密中继(规划中)

NSGW 还可以作为不解密 WireGuard 中继(peer-relay 模式),NSC ↔ NSN 端到端加密、NSGW 只见密文,详见 nsgw/peer-relay-protocol.md。当前 mock 未实现,已设计 gateway_wg_relay SSE 事件预留。

#6.4 连接模式:注册时声明,不是运行时回退

NSC ↔ NSN 走哪条路径,是 NSN / NSC 在 /machine/register 时声明的支持集合 + NSD 策略层选定的激活模式,不是运行期探测失败后再申请的产物。这把决策从数据面挪到了控制面,可预测且无反馈环。

模式数据面路径NSN 看到的 NSC peer EndpointNSGW 角色NSGW 是否见明文兼容存量 WG 客户端
directNSC ↔ NSN(P2P,可叠加 hole-punch)NSC 真实 endpoint不参与—✓
relayNSC ↔ NSGW ↔ NSN(端到端)NSGW endpoint,peer pubkey 仍是 NSC 真实 pubkey不解密中继✗✓
terminateNSC↔NSGW + NSGW↔NSN(双段独立 WG)NSGW endpoint,peer pubkey 是 NSGW终结✓✓
wssNSC↔(TCP/WS)↔NSGW↔(WG)↔NSN(NSC 端非 WG)WSS 帧中继 + 出口走 WG部分NSC 端非 WG

注册流程的字段(规划,加入 POST /api/v1/machine/register body):

  • supported_link_modes: ["direct", "relay", "terminate", "wss"] —— 该节点物理上支持的子集
  • preferred_mode(可选) —— 同等可行时的优先项

NSD 在策略授权时为每条 (NSC, NSN) 边取 NSC.supported ∩ NSN.supported 的非空交集,选最优先项,材料化 为对应的 wg_config(双方)+ 必要时的 gateway_wg_relay(NSGW),一次性下发完成。

NSN / NSC 端不需要实现"直连超时 → 申请中继"的探测器与控制信道;模式切换属于策略变更(admin 调权限或节点重新登记 supported 集合),仍由 NSD 推送。auto-fallback 可作为基础模型上的可选附加层(NSC / NSN 端在 supported_link_modes 内自动降级),不属于默认行为。

#6.4.1 默认模式由 NSGW 运营方决定(规划)

supported_link_modes ∩ 给出 NSC 与 NSN 物理上能选的集合,默认从中挑哪一个取决于 NSGW 自身的信任分层 —— 由 NSGW 在 gateway/report 时声明 operator 字段,NSD 据此为每条 (NSC, NSN) 边设默认优先级:

operator含义默认模式理由
self-hosted客户在自己 PoP 部署的 NSGWterminateNSGW 在客户信任边界内,见明文不增加暴露面;同时拿到 /client 入口预拒、流级计费、MSS clamp、协议异构等"网关见明文"才有的能力
managedNSIO 或第三方 SaaS 运营的云端 NSGWrelayNSGW 在第三方信任域,结构性不可观测客户明文;客户显式 opt-in 才升级到 terminate,与"结构上不可读 ≠ 承诺不读"的产品立场一致
partnerISP / 合作伙伴托管relay信任假设介于两者之间,保守取 relay

与"未声明能力 NSD 不能凭空生成"原则同构:默认信任边界跟着 NSGW 运营方走;客户要扩大边界(让 NSGW 见明文)必须通过 preferred_mode = "terminate" 显式声明,等价于在合规上接受"运营方有能力观测明文"。这个 opt-in 在 NSD 端审计可见。

relay 默认带来的副作用(云端形态需要相应补齐):

失去的能力补救路径
/client 入口 ACL 早拒(~99% 越权拦在网关)移到 NSC 侧出站 ACL 预检(acl_config SSE 事件 NSC 端已就位、未消费;§4 表);NSN 仍兜底终决。两级信任从"NSGW 偏宽 + NSN 偏严"变成"NSC 自检 + NSN 终决",信任根去中心化
per-org 精确流级计费NSN 报 per-service 字节;NSGW 仍能算密文 4-tuple byte counters,但失去 L4+ 切分粒度
MSS clamp / tc 整形NSC 端 userspace WG 自己处理
WAF / mTLS / OIDC 中间件这些是 §6.2 公网入口(https)路径上的能力,与 relay/terminate 选择正交 —— 启用公网入口本身就意味着接受 NSGW 在那条路径上见明文
NSN 侧 peer 表 O(NSGW) 扩展性退化为 O(NSC),是硬代价——大型租户在 managed 形态下需要 NSN 用 wireguard-go userspace + sharding 应对,无法从其他地方补

自部署 NSGW 不变:客户在自家 PoP 跑 NSGW 时,operator = self-hosted,所有"网关见明文"特性继续是免费默认,与现有部署形态零差异。

#6.5 Service Backend 类型与声明权(规划)

当前实现里"服务"与"NSN"是 1:1 绑定:每个服务必须在某个 NSN 的 services.toml 里声明、由该 NSN 进程承接终端流量并做 ACL 终决。这是默认且最常用的形态,但不是"服务"概念的唯一可能形态。本节统一描述两条相关扩展——backend 类型的多元化、以及服务声明权的对称化。

#6.5.1 三类 service backend

随着 NSIO 覆盖面扩大,以下场景越来越普遍:访问 SaaS API、按特定 egress region 适配 IP allowlist、把跨云 PaaS 端口暴露给开发者、让 NSC 把"全部互联网流量"经特定 PoP egress(类似 Tailscale exit node)。它们都符合"我只想要一个被分配 VIP / 路由的入口,backend 是哪种形态用户不关心"。

Backend 类型数据路径终决 ACL 在哪适用场景
NsnBacked { site, port }(现有)NSC → NSGW → NSN → 本机/LAN 服务NSN(权威终决 + services.toml 兜底)需要进入站点内网、需要 L3 模型、需要 smoltcp 解析、需要权威 ACL 终结的传统场景
GatewayEgress { gateway_id, target_host, target_port, transport }(规划)NSC → NSGW → 直接 TCP/UDP 到指定目标NSGW(此时无 NSN,NSGW 升级为权威决策点)SaaS / 公网 API egress、IP allowlist、轻量"虚拟服务"
GatewayExit { gateway_id, scope }(规划,exit node 模式)NSC → NSGW → 公网(任意目标)NSGW(per-user / per-group exit policy,fail-CLOSED)"把整段默认路由经此 PoP 出去"——开发者跨地 egress、合规出口、移动用户绕墙

scope 取值:default-route(等价 0.0.0.0/0,完整 exit node)、cidr: "10.0.0.0/8"(部分 exit,只这段经过)、或 acl-driven(由 ACL 决定哪些流量启用 exit)。

与 NSC 数据面模式的耦合:

  • NsnBacked / GatewayEgress 在所有数据面模式下工作(VIP 段 + WSS 流);
  • GatewayExit 实质上需要 TUN 数据面——userspace 模式的 VIP 段无法捕获任意公网 IP,HTTP 代理只能覆盖 HTTP/CONNECT;exit node 启用后 NSC 需在系统路由表写 0.0.0.0/0 dev nsio0(或目标 CIDR)。详见 nsc/roadmap.md F.1 TUN 数据面真实化。

TUN 模式的寻址模型选择(VIP vs passthrough):VIP 段(127.127/16 userspace、100.64/16 TUN)是 userspace 约束的延续,不是 TUN 模式的硬要求。TUN 已获 root 并管控 TUN 设备,可以选择直接路由到站点 CIDR(passthrough,等效 WireGuard subnet router / Tailscale subnet 路由)。NsnBacked 服务的 addressing 字段(NSN 端 services.toml 声明)在 "vip" 与 "passthrough" 间二选一,二者可共存:虚拟服务(GatewayEgress)走 VIP,L3 整段网络服务走 passthrough。详见 nsc/architecture.md §2.8.1。

#6.5.2 服务声明权的对称化

声明权当前不对称:只有 NSN 能声明自己的服务(services.toml 本地白名单 + services_report 上报),NSGW 是纯被动消费者——只接收 NSD 推送的 wg_config / routing_config / acl_projection,自己不声明能服务什么。

这条不对称在引入 §6.5.1 的新 backend 类型后无法继续维持:GatewayEgress 与 GatewayExit 描述的是网关的网络位置 / 出口能力,只有网关自己知道"我能到达 SaaS 后端的网段"、"我所在 PoP 提供哪个国家的 egress IP"、"我有没有专线打到合作伙伴"。把这些事实交给 NSD 维护,等于让"远离数据面的中央数据库"声明"靠近数据面的网关能干什么",违反 NSIO 的"上报驱动合成"原则。

由此引入对称的服务声明权:

声明者通道可声明的 backend 类型说明
NSN(现有)POST /api/v1/services/report,源自本地 services.tomlNsnBacked节点本地白名单是 ACL 兜底,不可绕过
NSGW(规划)POST /api/v1/gateway/services_report(或扩展现有 gateway_report body),源自本地 gateway_services.tomlGatewayEgress、GatewayExit网关本地清单是该网关 ACL 终决的兜底——admin 在 NSD 端不能让 NSGW 暴露它本地清单中没有声明的目标
NSD admin(管理面)Admin UI / API任意类型(裁剪后下发)管理员选择"启用哪些声明给哪个 realm / role";不能凭空生成 NSN/NSGW 没声明的能力

声明对称带来的副作用:NSGW 与 NSN 一样持有"自身能力的本地权威清单",这同时是 ACL 终决的最后兜底——gateway_services.toml 里没有的目标,即便 NSD 推下来,NSGW 也拒绝中转。这与 NSN 的 services.toml floor 是同一种安全模型。

NSC 与现状一致——routing_config 给它的就是"site 名 + service 名 + VIP",NSC 不感知 backend 是 NSN 还是 NSGW(egress / exit);open_stream / VIP listener 的语义不变,唯一例外是 GatewayExit 需要 NSC 切到 TUN 数据面以承接默认路由。改动集中在 NSGW(L4 egress + exit NAT + 完整 ACL 引擎 + 服务声明上报)与 NSD(扩展声明合成,接受来自网关的服务上报)。

信任模型的关键变化:NsnBacked 下 NSN 是 ACL 终决点+本地白名单兜底;GatewayEgress / GatewayExit 下没有 NSN,NSGW 必须承担权威终决——这违反了 §7.1 中"NSGW 仅做预拒,不做权威决策"的当前不变量。因此这两类 backend 的实施需要在 NSGW 引入完整 ACL 引擎(而不仅是预拒投影),与现有"两级信任"形成正交的"纯 NSGW 终决"分支。该 carve-out 仅作用于 GatewayEgress / GatewayExit 路径,不影响 NsnBacked 的现有信任边界。

详细演进项见 nsgw/roadmap.md 与 nsgw/architecture.md §2.8.1;NSC 侧 NsnBacked / GatewayEgress 零改造,GatewayExit 需要 TUN 数据面真实化(nsc/roadmap.md F.1)。

#7. 信任边界与失败域

#7.1 信任边界

边界谁在线内谁在线外
私钥仅本节点(NSN / NSGW / NSC)NSD、所有传输通道、所有日志、所有备份
业务流量明文NSN(ACL 终决点);终结模式下的 NSGW;浏览器中继模式下的 NSGW;NSD
权威 ACL 决策NSNNSGW(仅做预拒,可偏宽不可偏严)
服务白名单NSN(本地权威)NSD(不能反向告诉 NSN 能代理什么)

#7.2 失败域

故障业务连接控制变更新节点接入
NSD 整体不可达既有连接继续不能下发新策略不能注册新节点
某个 NSGW 不可达NSC / NSN 切到备网关;旧连接断(lazy binding 让新连接立即用新网关)不影响不影响
某个 NSN 不可达该 site 服务不可达不影响不影响
NSC 不可达本机用户进程访问失败不影响不影响
SSE 与 NSD 短暂断链NSGW ACL 投影 fail-open(偏宽);NSN 维持上一次配置暂停热更新暂停

NSD 故障域被压缩到"无法变更策略 / 无法新建注册"——这是 NSIO 把控制面与数据面解耦的最重要收益。

#8. 阅读路线

  • 想看 NSIO 提供的能力与不可放弃差异点 → 首页 index.md
  • 想知道某个组件具体做什么 / 不做什么 → 对应组件目录的 architecture.md
  • 想理解 WireGuard 不解密中继的协议细节 → nsgw/peer-relay-protocol.md
  • 想看演进路线 → 各组件目录的 roadmap.md