NSGW · 架构与功能设计
本页从纯架构视角描述 NSGW(Network Service Gateway) 的功能划分与设计特点。改造路线见 roadmap.md。
1. 角色定位
NSGW 是 NSIO 生态的数据面网关,通常部署在 PoP / 公有云 region。它对外暴露公网 IP,对内与 NSN 通过 WireGuard 隧道连接,并以三类协议入口承接外部流量:
- WireGuard UDP:NSC 与 NSN 都可以通过 WireGuard 接入,获得最低延迟的 L3 全隧道。同一个 51820/udp 端口同时支持两种语义:
- 终结模式(默认):NSGW 持有私钥并参与握手,解密后按 allowed-ips 路由。
- 不解密中继模式:NSGW 不参与握手、不持有相关密钥,只在两端之间桥接密文 UDP 包,兼容存量 WireGuard 客户端,作为 NSC ↔ NSN 直连失败的兜底。
- WSS 中继:UDP 被严格阻断时的备选通道,以 WebSocket 多路复用承载 TCP / UDP 业务流量。
- 公网流量入口(HTTPS 反向代理):不依赖 NSC 的独立流量承载形态——浏览器、API 客户端、移动端、第三方系统都可以直接从公网到达本网关,基于 Host 头路由到对应 NSN 的服务端口。可选挂接外部鉴权(OIDC / mTLS / API key / 签名 URL / Basic Auth)以覆盖"既无 NSC 也无 NSD JWT"的访问主体识别;鉴权完成后流量经 WireGuard 段 2 送达 NSN,授权裁决仍在 NSN。
NSGW 的核心定位是"协议无关的数据面中继 + 网关级安全 + 网关级容灾",具体的策略求值与连接合规由 NSN 终决。
NSGW 的运行约束:
- 被动:NSGW 不主动心跳上报,只响应 NSD 的探测;它的职责是保持 SSE 订阅就绪、保持 WireGuard / HTTPS / WSS 三条入口可达。
- 无身份维护:NSGW 不签发 token、不维护用户身份与会话状态。对 NSC 入口校验 NSD 颁发的 JWT 以确认
machine_id(§2.6);对公网入口可选作为外部 IdP 的 RP / 鉴权代理,但仅在请求级别完成令牌校验与主体提取,不持有会话(§2.4.1)。
- 非权威 ACL:NSGW 在
/client 入口做"两级信任的前一级"过滤,容许偏宽,作为 NSN 终决前的早拒优化。
2. 功能模块划分
NSGW 内部按职责切分为六条核心职责,加上一组运营 / 容灾 / 观测能力。
2.1 WireGuard UDP 终结(self-hosted 默认 / managed opt-in)
- 默认形态依 NSGW 运营方而定:
operator = self-hosted 时这是默认模式;operator = managed / partner 时默认走 §2.2 不解密中继,客户 opt-in 才升级到本模式。详见总体架构 §6.4.1。
- 内核接口承载:在网关内核接口上接收 WireGuard 握手与加密包,解密后通过本机路由送达对应 NSN 的虚拟 IP。
- peer 动态同步:NSD 通过 SSE 推送 WireGuard 配置(peer 公钥与 allowed-ips),NSGW 以增量 diff apply 的方式维护 peer 表。
- AllowedIPs 即路由:NSGW 不维护应用层路由,WireGuard 的 allowed-ips 字段同时承担"加密路由"与"网关内部转发表"两重语义。
- MTU / MSS clamp:为避免跨隧道分片,在适当方向做 MSS 修正。
- 加密边界:WG 会话在 NSGW 切断 + 重建(NSC ↔ NSGW、NSGW ↔ NSN 是两段独立握手),网关持有自身私钥并能看到隧道内的明文 IP 包。这是 self-hosted 默认模式;managed 形态结构性不见明文,详见 §2.2。
2.2 WireGuard 不解密中继(Peer Relay 模式 / managed 默认)
NSGW 除了 §2.1 的"WG 终结"以外,还可以不解密地把 WireGuard UDP 数据报在两端之间转发。这条路径既是 self-hosted NSGW 在 NSC ↔ NSN 直连失败时的兜底通道,也是 managed / 云端 NSGW 的默认形态——结构性不可观测客户明文,客户 opt-in 才退回 §2.1 的终结模式。运营方分层与默认策略见总体架构 §6.4.1。设计参照 Tailscale Peer Relay:relay 节点只看密文,端到端会话仍由两端的 WG 直接协商。
协议层细节(mac1 demux / receiver_index 表 / 与原生 WireGuard 的兼容矩阵)见 peer-relay-protocol.md。
- 加密边界保留在两端:WG 握手与会话密钥仅在 NSC 与 NSN 两侧生成,NSGW 物理上无法读取明文。终结模式下 NSGW 持有自身私钥并能解密(等同隐式信任根);中继模式下 NSGW 退化为"可观测密文 4-tuple 的转发器",受信级别下降一档。这是 managed / SaaS 运营 NSGW 的合理默认(结构性零观测),也适用于跨租户共享的网关或客户希望审计上"运营方无解密能力"的部署形态。
- 兼容存量 WireGuard 客户端:中继逻辑全部在 NSGW 一侧实现,对端 WG 实现无需协议扩展、无需版本升级。内核态 WireGuard、
wg-quick 静态配置、BoringTun、商用厂商 WG 客户端都能在不修改的情况下被中继。这是"NSC 端复用存量 WG 客户端"以及"NSN 与第三方 WG 节点互联"等场景的关键支撑。
- NAT 穿透兜底:NSC 或 NSN 任意一方处于对称 NAT / 严格防火墙时,直连失败,但双方都能 outbound 到 NSGW 公网 IP。中继模式提供"用 WG 自己的协议穿越严防"能力,延迟与吞吐优于 §2.3 的 WSS 中继(WG-over-UDP 优于 WG-over-WS-over-TCP)。
- 寻址机制(实现路径):NSGW 要在不解密的前提下知道"这个 UDP 包应该转发给谁",可选方案有两类:
receiver_index 桥接:WG 协议头中的 receiver_index 由对端在握手响应中分配,后续 transport 包以此为路由键。NSGW 在握手阶段通过 NSD 下发的"中继配对表"识别 init / response 双方,记录 receiver_index ↔ peer 4-tuple 映射,后续数据包按 receiver_index 桥接。
- 每对 peer 一个监听端口:NSD 为需要中继的每对 peer 分配独立 UDP 端口,两端 WG 配置都指向该端口,NSGW 按端口 1:1 转发。简单稳定,代价是端口数与中继对数线性。
- 两种实现都不需要 NSGW 持有任何相关 peer 的私钥与对称会话密钥。
- 触发逻辑:模式由 NSN / NSC 在
/machine/register 时声明的 supported_link_modes 与 NSD 策略层共同决定(详见 总体架构 §5.4);NSGW 完全被动,仅消费 NSD 通过 SSE gateway_wg_relay(规划)推下来的中继配对表,不主动决策、也不接收 NSC/NSN 的运行期申请。
- 与 hole punch 的关系:UDP hole punch(参见 §2.7)是"协助直连"工具,中继模式是 hole punch 仍然失败后的兜底。选路上前者优先。
2.3 WSS 中继(WsFrame)
- 会话缝合模型:NSC 通过
/client 进入网关,NSN 通过 /relay 进入网关,两侧的会话在网关内被缝合为一对一的字节流通道。
- 多路复用:同一条 WebSocket 长连承载多条逻辑流(TCP 与 UDP 均可),通过自定义 WsFrame 协议在帧头标识流 ID、命令类型与负载。
- 本地 Fallback:当目标 site 在该 NSGW 上没有活跃 NSN 会话时,网关可以选择在本机直接打开到 NSN 上游服务的 TCP / UDP 连接,作为 NSC 视角下的"无感降级"。
- 协议契约:WsFrame 的字节级布局是数据面的硬契约,所有实现必须严格一致,任何字段语义变化都必须升级版本。
- 与 §2.2 不解密中继的分工:WSS 中继针对"UDP 完全被阻断"的环境;不解密中继针对"UDP 通但无法直连"的环境;两者承担不同的失败域。
2.4 公网流量入口(HTTPS 反向代理)
NSGW 在这条路径上扮演的是独立流量承载方:与 §2.1–§2.3 都需要 NSC / NSN 端的 WireGuard / WSS 客户端协同不同,这里不要求公网侧运行任何 NSIO 客户端,任何标准 HTTPS 客户端(浏览器、CLI、移动端、SaaS 回调、合作伙伴系统)都能作为流量源,经此承载入 NSN。这是 NSGW 在"无 NSC 部署"形态下的主入口。
- TLS 终结 + Host 路由:网关在 443 端口接收公网请求,做 TLS 终结后基于 Host / SNI 选择目的 site,将明文 HTTP 请求(或字节流)经 WireGuard 隧道送达 NSN。
- 边界身份认证 vs 服务级授权(职责分层):NSGW 在这条路径上的应用层介入严格限定为"边界身份认证"(确认谁在敲门),不进入"服务级授权"(决定能不能进哪个服务 —— 由 NSN 终决):
- NSGW 不读 HTTP 路径、不重写业务头、不做应用层授权;
- 但可以挂接外部鉴权链,把"主体身份"标准化后透传给 NSN(详见 §2.4.1);
- NSN 仍是权威 ACL 终决点,NSGW 给出的"主体"对它而言是输入而非结论。
- 动态路由配置:NSD 通过 SSE 推送路由配置,NSGW 原子更新本地动态路由表,反向代理子系统自动 reload。
- 证书来源:开发态使用自签证书,生产态由网关自身或前置入口层(traefik / Cloudflare / 云负载均衡器)负责 ACME / 企业 CA 集成。
2.4.1 外部鉴权:无 NSC 公网入口的主体识别(规划)
NSC ↔ NSN 路径上,访问主体由 NSD 颁发的 JWT 在 /client 入口确认(§2.6);公网入口路径上没有 NSC,也没有 NSD JWT。这条路径要承载非匿名业务流量(SaaS 内部 API、合作伙伴回调、运维直登 dashboard、移动端访问内网服务等),就需要在 NSGW 入口处接入外部鉴权,把"匿名 TLS 连接"升级为"带主体的连接",再交给 NSN 做服务级 ACL 终决。
- 鉴权方式可插拔:在同一条 vhost / 路由规则上,可挂接以下任一(或多个):
- OIDC / OAuth2:对接外部 IdP(企业 SSO、社会化登录),NSGW 充当 OIDC RP,完成 code 流程或 ID token 校验,把
sub / email / groups 等声明导出。
- mTLS 客户端证书:与企业 CA / 私有 CA 联动,把
CN / SAN / OU 作为主体来源。
- API key / Bearer token:对接 API key store(本地或外部 KMS),静态密钥适合机器到机器场景。
- 签名 URL / HMAC 请求签名:适合一次性 / 短时效授权回调链路。
- Basic Auth:仅作为最低门槛兜底,不推荐生产长期形态。
- 匿名直通:显式声明的公开服务(状态页、登录页本身、webhook 接收端等)允许跳过鉴权,直接进 NSN。
- NSGW 不维护用户状态:即使做了 OIDC 流程,NSGW 也只在请求级别完成"令牌校验 → 主体提取",不存会话(会话/cookie 由 NSN 上的应用持有,或由前置 IdP 的 session 控制)。这是保住 §4.2 "网关无状态化"的关键。
- 主体到 NSN 的透传:鉴权产物以受 NSGW 签名的内部头部(规划:
X-NSIO-Subject + X-NSIO-Subject-Sig)注入到 NSGW → NSN 段的 HTTP 请求,NSN 侧的 ACL 引擎据此与 acl_config 中的 user / group / realm 规则求值。NSN 必须验证签名以拒绝伪造头部。
- 配置承载:NSD 通过规划中的 SSE
gateway_http_config 下发外部鉴权链与每个路由的鉴权策略(IdP endpoint、JWKS URI、API key store、mTLS CA bundle、跳过鉴权的路径白名单),与 routing_config 同样原子热更新,无需重启。
- 失败模式:鉴权未通过 → 返回 401 / 403,不进入 WG 隧道,从源头降低对 NSN 与 site 内部资源的暴露面。鉴权后端(IdP / JWKS / KMS)短暂不可达时,优先沿用本地缓存的 JWKS / key,缓存全部过期后 fail-CLOSED(与 §2.6 ACL projection 的 fail-open 显式相反——这里是"未识别即拒",不存在"宽容放行"语义)。
- 与 §6.5.1 backend 类型的关系:外部鉴权与 backend 类型正交。
NsnBacked 路由上,鉴权产物给 NSN 做服务级 ACL;GatewayEgress / GatewayExit 路由上,鉴权产物在 NSGW 自身的完整 ACL 引擎上求值(因为没有 NSN 兜底,见 §2.8.1.3)。两条路径共用同一套外部鉴权链,只是下游消费者不同。
2.5 与 NSD 的注册表同步
NSGW 启动时与 NSD 完成双向握手,并维持长连订阅:
- 机器注册:把网关本身作为一台 gateway 类型机器登记到 NSD,带重试。
- 网关端点上报:把可达的 WireGuard 端点与 WSS 端点上报给 NSD,由 NSD 解析后广播给所有 NSN(用于 WireGuard peer 表)与 NSC(用于选路)。
- SSE 订阅:订阅 WireGuard 配置(peer 同步)、路由配置(HTTPS 反向代理路由表)、ACL 投影(
/client 入口预拒副本)。
- 健康协议:对外暴露就绪端点供编排系统探测,对外暴露公钥端点供 NSD 校验一致性,以及测试专用的强制关停端点(生产必须禁用)。
2.6 /client ingress 的 ACL 预过滤
- 两级信任的前一级:NSGW 在 NSC 进入
/client 时已经校验过 JWT,因此可以在转发 WsFrame 的"打开流"请求之前,基于 ACL 投影做一次预拒。
- 允许偏宽:NSGW 持有的 ACL 投影只是 NSN 权威 ACL 的子集(不含 services 白名单的兜底层),设计上允许它判断为"放行",由 NSN 做最终拒绝;但反之不允许 NSGW 偏严。
- 失败时 fail-open:当 NSGW 与 NSD 的 SSE 断连导致 ACL 投影过期时,选择 fail-open 而非 fail-close,避免"NSGW 短暂不健康 → 全站拒"的运维故障模式。
- 拒绝原因可观测:网关预拒时通过结构化的关闭帧把原因传递回客户端,既给用户即时反馈,也给排错提供证据。
2.7 选路与多区域
NSGW 自身不负责"哪个用户走哪个网关"的决策,这部分逻辑放在 NSC / NSN 侧:
- NSGW 进程独立:每个 NSGW 是独立进程,只与 NSD 对话,网关之间不互相感知。
- 客户端选路:NSN / NSC 内部的多网关管理器持有完整网关拓扑,按"最低时延 / 轮询 / 主备"等策略选择主网关。
- 两层 fallback 正交:
- 网关级 fallback —— 主网关整体不可用时切到备网关。
- 传输级 fallback —— 主网关 UDP 不通但 TCP 通时切到 WSS 中继。
- 健康参数:网关探测以秒级 RTT 探测为基础,周期性健康检查(规划)用于及时回收 zombie 网关。
2.8 安全与限速
NSGW 是网络层的"挡门人",当前形态以 TLS 与 PROXY Protocol v1 为主,生产化沿以下方向扩展:
- 网络层防护:UDP flood 限流、IP 黑名单、CrowdSec 集成、Anycast IP 抗 DDoS、L3-L7 多层防护。
- 应用层防护:WAF、ext_authz、mTLS 终结、Resource 级访问鉴权(取决于路线 A / B 的选择)。
- 连接级中间件:CIDR allow / deny、GeoIP、连接速率与并发上限、fail2ban 式自动封禁、连接配额。
2.8.1 L4 egress 与"虚拟服务" / Exit Node(规划)
NSGW 当前作为数据面中继,核心责任是把 NSC 的字节流转交给 NSN;§2.3 已经埋了一条"目标 site 在该网关上没有活跃 NSN 会话时,本地直接打开到上游服务的 TCP/UDP"的降级 fallback。把这条 fallback 升格为一等公民,得到两类新 backend(见总体架构 §6.5.1):
2.8.1.1 GatewayEgress —— 指定目标的 L4 转发
- 声明形态:
backend = GatewayEgress { gateway_id, target_host, target_port, transport }。该服务通过 routing_config 派生出 <service>.<virtual-site>.n.ns + VIP,与 NSN 后端的服务在 NSC 视角下完全一致。
- NSGW 行为:收到 NSC 通过 WSS / 段 1 WG 送来的"开流"请求,直接
TcpStream::connect(target_host, target_port) 或 UDP 等价路径,然后双向 copy。不经过任何 NSN。
- 典型用途:
- SaaS API egress ——
api.openai.com:443 通过位于 Tokyo region 的 NSGW 出口,合规走特定地理位置;
- IP allowlist 适配 —— 合作伙伴 API 仅放行 NSGW 出口 IP,客户端无需自己维护这层;
- 轻量"虚拟服务" —— 无需在远端站点部署 NSN,只要 NSGW 网络上能到目标即可暴露给所有 NSC;
- 多 PoP egress 选择 —— 同一逻辑服务对不同用户群按 region / 租户路由到不同 NSGW egress。
2.8.1.2 GatewayExit —— Exit Node 模式
- 声明形态:
backend = GatewayExit { gateway_id, scope },scope ∈ { default-route, cidr: "<CIDR>", acl-driven }。
- NSGW 行为:从段 1 隧道(WG)收到任意目标的 IP 包,做 SNAT 到 NSGW 公网 IP,转发出去;返回包按 conntrack 反向送回。语义等同于 Tailscale exit node 或传统 VPN 网关的"全流量隧道"形态。
- 客户端要求:NSC 必须运行在 TUN 数据面下——userspace 模式只能捕获
127.127/16 段 VIP,无法承接默认路由;HTTP 代理只能覆盖 HTTP/CONNECT。详见 nsc/roadmap.md F.1 TUN 数据面真实化。
- 典型用途:
- 跨地 egress —— 远程开发者从亚太工作但需要从美国 IP 访问;
- 合规出口 —— 全部流量须经审计 PoP;
- 移动用户 / 受限网络绕墙 —— 网络上不可达公网时,通过 NSGW 兜底走出去。
2.8.1.3 通用约定
- 配置承载:沿用规划中的
gateway_l4_map SSE 事件(见 index.md 与 roadmap.md);backend 字段为 NsnBacked | GatewayEgress | GatewayExit 三选一的 tagged union。
- 信任边界的副作用:
GatewayEgress / GatewayExit 下没有 NSN 兜底,NSGW 必须承担权威 ACL 终决,这与 §6 / §7 描述的"NSGW 仅做预拒、不做权威决策"形成显式破例。设计上不让它回潮影响 NsnBacked 信任模型——在 NSGW 内部把两类终结路径分开:
| 路径 | ACL 角色 | 失败模式 |
|---|
出口走 NSN(NsnBacked,现状) | 仅预拒,fail-open | 由 NSN 终决,NSN 兜底 |
出口走本机 connect(GatewayEgress)/ NAT(GatewayExit)(规划) | 完整 ACL 终决,fail-CLOSED;gateway_services.toml 本地清单是兜底底线(见 §2.8.2) | NSGW 直接拒绝;无下游兜底 |
- 与 §2.3 WSS 中继 fallback 的区别:§2.3 fallback 是"NSN 应该在但当前不在",fallback 目标来自 NSN 的服务声明,语义上仍是
NsnBacked;GatewayEgress / GatewayExit 目标来自 NSGW 自己声明的 gateway_services.toml(见 §2.8.2),从声明起点就不打算经过 NSN。底层共用 connect() + copy_bidirectional,但配置来源、信任假设、运维语义都不同。
2.8.2 NSGW 作为服务声明者(规划)
服务声明权当前不对称:只有 NSN 能声明自己的服务(本地 services.toml + services_report 上报),NSGW 是纯被动消费者。这条不对称在引入 §2.8.1 后无法继续维持——GatewayEgress / GatewayExit 描述的是网关的网络位置 / 出口能力,只有网关自己知道"我能到达哪些 SaaS 后端网段"、"我所在 PoP 提供哪个国家的 egress IP"、"我有没有专线连合作伙伴"。把这些事实交给 NSD 维护,等于让"远离数据面的中央数据库"声明"靠近数据面的网关能干什么",违反 NSIO 的上报驱动合成原则。
NSGW 因此对称地获得服务声明权:
- 本地清单:
gateway_services.toml(或同等结构),格式:
[[egress]]
service = "openai-api"
target_host = "api.openai.com"
target_port = 443
transport = "tcp"
acl_ref = "saas-egress-tokyo"
[[exit]]
service = "exit-node-tokyo"
scope = "default-route"
acl_ref = "exit-node-allowed"
- 上报通道:
POST /api/v1/gateway/services_report(或扩展现有 gateway_report body 增字段 egress_services / exit_services)。
- NSD 行为:把网关上报的服务清单纳入与 NSN 同一份"服务目录",经策略 / ACL 裁剪后下发给 NSC 与对应 NSGW 自身(
routing_config + gateway_l4_map)。
- 本地清单是兜底:与 NSN
services.toml 同语义——admin 在 NSD 端不能让 NSGW 暴露它本地清单中没有声明的目标,即便 gateway_l4_map 推下来与本地清单不一致,NSGW 取交集;services.toml 的"floor"不可绕过。
- 管理面仍可干预:管理员在 NSD 端选择"哪些已声明能力对哪个 realm / role 启用",但不能凭空生成 NSN/NSGW 没声明的能力——延续 NSIO "节点声明能力,中央做编排"的关系。
这条扩展使 NSN 与 NSGW 在声明权上对称:都是"自己最了解自己的能力"的本地权威,NSD 只做合成与裁剪,不替它们决定能力边界。
2.9 观测、审计与计费埋点
- 连接级观测:Prometheus 指标、OpenTelemetry trace、结构化访问日志、实时拓扑上报、采样控制。
- 审计与合规:连接级审计日志、敏感操作告警。
- 资源与计费:每 peer / 每组织的精确流量计量、QoS / tc / eBPF 整形、计费埋点;NSGW 是 NSIO 中唯一自然适合做出账聚合的节点。
3. 三类入站矩阵
NSGW 同时暴露三个入站协议端口,功能上互补:
| 端口 | 协议 | 模式 | 进入方 | 用途 |
|---|
| WireGuard UDP | L3 隧道 | 终结(默认) | NSC / NSN | 最低延迟,网关参与握手与解密 |
| WireGuard UDP | L3 隧道 | 不解密中继 | NSC / NSN(端到端) | NSC ↔ NSN 直连失败兜底,网关只见密文,兼容存量 WG 客户端 |
| HTTPS 443 | TLS + L7 反代 | — | 任意公网 HTTPS 客户端(浏览器 / API / 移动端 / 第三方) | 不依赖 NSC 的独立流量承载;可选挂接外部鉴权(OIDC / mTLS / API key / 签名 URL / Basic Auth)做边界身份认证,授权裁决仍由 NSN 终决 |
| WSS | WsFrame 多路复用 | — | NSC / NSN | UDP 受阻时的备选数据通道 |
三个端口共享同一份网关身份与同一份 NSD 订阅状态,但在数据通路上互相独立,各有自己的会话生命周期与失败模式。WireGuard 入口的两种模式由 NSD 下发的中继配对表决定,在同一个 51820/udp 端口上区分:不在配对表中的握手按终结模式处理,在配对表中的按 4-tuple / receiver_index 桥接,互不串扰。
4. 设计特点
4.0 三类部署形态共存
NSGW 在同一进程内同时支持三类互不依赖的部署形态,这三类形态决定了入口面对的是谁、是否需要 NSC、以及鉴权由谁承担:
| 形态 | 入口主体 | 是否需要 NSC | 鉴权来源 | 出口去向 |
|---|
| NSC 隧道接入 | 已部署 NSC 的内部用户 / 站点 | 是 | NSD JWT(§2.6) | NSN(NsnBacked) |
| 公网流量承载(§2.4) | 任意 HTTPS 客户端,无 NSC | 否 | 外部鉴权(OIDC / mTLS / API key / …,§2.4.1)或显式匿名 | NSN(NsnBacked),WG 段 2 |
| 网关 egress / exit(§2.8.1) | NSC | 是(承接 VIP / 默认路由) | NSGW 完整 ACL 终决(§6) | 公网 / SaaS,不经 NSN |
三类形态在 NSGW 内共享身份、配置同步与观测,但数据通路彼此独立、信任模型彼此正交。这是后面"协议无关中继"(§4.1)与"traefik 是早期选择"(§4.6)的前提。
4.1 协议无关的中继
WireGuard / WSS / HTTPS 三条数据通路在 NSGW 内由各自子系统承载,共享身份与配置同步,但不共享数据通路。这种"多协议同位"的设计直接面对真实网络环境的多样性:数据中心、办公网、移动运营商网络对协议有截然不同的偏见,NSGW 用"多协议并存 + 客户端侧选择"应对。
WireGuard 入口进一步分裂出两种语义(§2.1 终结、§2.2 不解密中继),在同一个 UDP 端口上共存:终结模式追求"网关侧最优路由与统一 ACL 决策点",中继模式追求"端到端加密 + 兼容任意 WG 实现"。这与设计原则"协议无关的字节中继"是同向的——把"是否解密"也变成网关的一个可选行为,而非硬约束。
4.2 网关无状态化
NSGW 不维护"用户业务态",所有应用层状态在 NSN(对话方向)或浏览器(直连方向)。NSGW 只承担字节中继 + 路由 + 预拒,这使网关的水平扩展、滚动升级、跨区 failover 都不必处理"会话迁移"这一最难的子问题。
4.3 配置全部来自 SSE
NSGW 的 peer 表、HTTPS 路由表、ACL 投影,都通过 SSE 单向接收,本地不维护"权威配置文件"。这避免了"两套真相"的一致性陷阱,也使 NSGW 故障重启后能无副作用恢复。
4.4 两级信任的 ACL
NSGW 不与 NSN 抢"权威 ACL 决策",但可以做"早拒"。设计原则:NSGW 偏宽 + NSN 偏严 = 安全。这一约束对 ACL 投影的过期、断链、空策略容忍度有明确指引(选 fail-open 偏宽,而非 fail-close 偏严)。
4.5 客户端选路 + 网关独立
"哪个用户走哪个网关"的决策在客户端侧(NSN / NSC),NSGW 之间互不感知。这种把"决策"留给客户端的设计,避免了网关侧需要维护"全局一致选路状态"的复杂度,同时让客户端可以在网关健康度变化时独立做出选择。
4.6 traefik 是早期选择,而非长期决策
早期形态把 traefik 作为 L7 入口,但随着 NSGW 职责扩展到 L4 端口映射与多 PoP 协同策略,traefik 的"南北向 HTTP 网关"定位与 NSGW 的"跨协议数据面中继"定位逐渐错位。两条演进路线被同时保留:
- 路线 A:NSGW 自研轻量 Proxy + 外部入口层(Cloudflare / ALB / 前置 envoy),NSGW 收敛为纯数据面与早期策略点。
- 路线 B:NSGW 内集成 envoy + xDS,NSD 提供 SSE → xDS 适配,获得完整 L4/L7 与 mTLS / SPIFFE 生态。
当前倾向路线 A 先行,保留向 B 演进的路径,方法是把 SSE 事件结构(gateway_http_config / gateway_l4_map)抽象到下游消费者无关。
5. 与其他模块的边界
NSGW 不做的事情:
- 不承担用户认证(由 NSD 完成)。
- 不做策略合并(由 NSN 的多控制面聚合层完成)。
- 不做权威 ACL 决策(由 NSN 终决)。
- 不维护应用层会话(HTTPS 由反代终结,WSS 只做字节中继)。
- 不分配虚拟 IP(由 NSC 在用户侧完成,或由 NSD 编排)。
- 不参与控制面合并联邦(NSD 之间互不感知,NSGW 也不参与)。
NSGW 实际只需要知道两件事:"这个公钥对应哪段 allowed-ips"以及"这个域名对应哪个 NSN 上的服务端口",其余全部来自 NSD 的 SSE 推送。
6. 演进方向
NSGW 的生产化沿"六大能力轴"展开:
- 连接能力:补齐 QUIC / Noise / MASQUE 数据面、UDP hole punch、内置 STUN / TURN、PROXY v2、mTLS 终结、SO_REUSEPORT 多进程、Gateway-to-Gateway Mesh。
- 路由与寻址:WireGuard peer 动态同步、HTTP/HTTPS 动态路由、SNI / L4 端口映射、Anycast IP、GeoDNS、跨网关热迁移、路由优先级回落、Path / Header-based routing、A/B 路由、Virtual Port 路由。
- 安全能力:基础限速、UDP flood 防护、CrowdSec、WAF、mTLS、零信任策略点、L3-L7 DDoS 防护。
- 容灾与运维:graceful drain / swap、蓝绿、session 快照、跨区 failover、连接 handoff、热升级。
- 观测与审计:Prometheus 指标、OpenTelemetry traces、结构化访问日志、实时拓扑上报、采样控制、审计落盘 + SIEM。
- 资源与计费:每 peer / 每组织精确计量、配额 / QoS、tc / eBPF 整形、计费埋点(billing/ingest)。
NSGW 的演进核心是把 SSE 驱动的控制契约与生产级数据面能力收敛到一套实现,并保留向 envoy + xDS 平滑切换的口径。无论选择哪条路线,客户端侧契约(.ns 命名、环回 VIP、ACL 仅允许、协议可插拔)对站点无感。
7. 协议层组件清单
按协议层把 NSGW 内部的组件做一次扁平汇总,详细职责见上文 §2。
7.1 入站协议监听器(三端口矩阵)
- WireGuard UDP 终结端:L3 全隧道入口,加密路由表与转发表合一。
- WireGuard 不解密中继器:与终结端共用 51820/udp 端口,不解密、不持有相关密钥,按 4-tuple /
receiver_index 桥接 NSC ↔ NSN 端到端 WG 会话。
- HTTPS 反向代理:TLS 终结 + Host / SNI 路由,作为浏览器与外部直连的入口。
- WSS 中继服务器:同时承担"客户端进入"与"站点节点接入"两端,在网关内部缝合为一对一的字节流通道。
- 健康端点:就绪探针、网关公钥校验、测试专用关停接口(生产必须禁用)。
7.2 控制面接入(客户端方向)
- SSE 订阅:消费 WireGuard 配置、路由配置与 ACL 投影三类事件。
- 注册与上报 REST 客户端:把网关本身登记为机器并上报可达端点,带重试。
7.3 数据通路处理
- WireGuard peer 同步器:SSE 驱动的增量 diff apply(终结模式)。
- WireGuard 中继配对表(规划):SSE
gateway_wg_relay 驱动,装载"NSC ↔ NSN 中继配对",用于 §2.2 不解密中继的 receiver_index / 端口寻址。
- HTTPS 路由动态生成器:SSE 驱动的原子写入 + 反代自动 reload,无需重启。
- 帧多路复用解析器:解析自定义二进制帧协议,用单条长连承载多条逻辑流。
- 会话缝合器:维护连接器流与客户端流的反查表;无可用站点会话时,网关在本地直接打开到目标的连接作为无感降级。
- ACL 投影装载器与预拒模块:
/client 入口预拒明确违规,fail-open;关闭帧携带结构化原因。
- JWT 校验器:
/client 入口拿到访问端 machine_id,作为预拒模块的主体来源。
7.4 规划中的扩展
- L4 端口映射 listener:由专用 SSE 事件驱动,支持任意 TCP / UDP 端口在网关上对外发布。
- L7 中间件链:公网入口边界身份认证(OIDC / mTLS / API key / 签名 URL / Basic Auth,服务于"无 NSC 独立流量承载"形态,见 §2.4.1)、限速、WAF、请求改写,由 SSE
gateway_http_config 驱动,无需重启热加载。
- 连接级中间件:CIDR allow / deny、GeoIP、连接速率与并发上限、自动封禁、连接配额、PROXY v2。
- 计费埋点:网关是 NSIO 中唯一适合做出账聚合的节点,精确按 peer / 组织计量。