Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

配置参考

守护进程从其工作目录读取单个 config.json(用 --config <path> 覆盖)。文件缺失时回退到 编译进二进制的默认值。解析器是严格的:未知结构、非法 CIDR 或越界取值都会导致 失败即关闭 的启动。部署前用 subnetrad --check 校验任何变更。

一个最小示例(config.example.json):

{
  "negotiation_version": 1,
  "local_tun_mtu": 1452,
  "listen_ports": [18020, 18023, 18026],
  "virtual_subnet": "10.0.0.0/24",
  "local_id": 1,
  "obfuscate": true,
  "peers": [
    { "id": 2, "endpoint": "203.0.113.2:18020", "allowed_src": "10.0.0.2/32", "name": "bj-office-gw", "psk": "…64 hex…" },
    { "id": 3, "endpoint": "203.0.113.3:18020", "allowed_src": "10.0.0.3/32", "name": "colo-hub",     "psk": "…64 hex…" }
  ]
}

顶层字段

字段类型默认说明
negotiation_version整数1线/配置版本,v1 固定为 1。为未来 静态 的每链路传输模式选择预留——绝非线上握手。
local_tun_mtu整数1452隧道 MTU,必须在 68–1500 内。默认值在 1500 字节承载上为 64 字节线开销留出余量。
listen_ports整数数组按角色而定(见说明)守护进程为承载绑定的 UDP 端口——显式列出(绝非范围计算)。本节点在 全部 端口上接收数据报,并按每个对端最近一次到达的本地 socket 回程发送(NAT 正确),因此单个端口被封锁不会让本节点下线。1–8 个端口,每个非零且互不相同。省略时默认值按角色而定: hub/manual 节点绑定完整端口集 [18020, 18023, 18026](它是可达端点,多端口可在单端口被封锁时容错),而 spoke 只绑定 [18020]——spoke 位于 NAT 之后,hub 始终回程到它的源端口,因此 spoke 上多余的监听端口只会闲置。两种角色都用 同一个数组字段 显式覆盖即可(例如 spoke 写 [18020],hub 写 [18020, 18023, 18026])。默认值刻意 不是 51820(WireGuard 的知名端口本身就是指纹)。
listen_port整数(未设置)单端口便捷/向后兼容写法:等价于 "listen_ports": [<port>]。当 listen_ports 存在时本字段被忽略;两者都省略时使用按角色而定的默认端口集。
virtual_subnetCIDR10.0.0.0/24本网格构建的叠加子网。
local_tun_ipCIDR(不设)本节点自身的叠加地址(主机 + 前缀),例如 10.0.0.2/24。用于生成主机网络规划、为 TUN 配置地址;守护进程 自行配置主机地址。role=spoke 需要一个本地目标(本字段 local_routes),并以它作为该 Spoke 的可达 IP。对 role=hub可选——推导出的表只转发给 Spoke,故不设它即让 Hub 保持纯中继、在叠加网络上 不可达;仅当需要访问 Hub 自身时才设置它(并追加一条本地投递规则)(详情)。
local_id整数0本节点网格 id。必须 非零、可放入 u161–65535),且当 peers 非空时与每个对端 id 不同。0 表示「单节点 / 无网格」。
peers数组[]配置的网格对端(固定容量、零分配)。见 对端字段
role字符串"manual"manualhubspoke。控制启动策略推导——见 角色
local_routesCIDR 数组[]role=spoke:本节点 本地 投递(到自身 TUN/主机)的子网。为空时使用 local_tun_ip(作为 /32)。
remote_routesCIDR 数组[]role=spoke经由 Hub 可达的子网。为空时,Spoke 把 virtual_subnet 路由到 Hub。
keepalive_secs整数角色默认内置 spoke→hub NAT 保活间隔。0 关闭(hub/manual 默认)。NAT 后的 spoke 默认 20。开启 obfuscate 时,每次间隔在 [secs/2, secs] 内随机化,使保活节奏不构成指纹。
obfuscate布尔true报头混淆默认开启:按包对 20 字节报头做 XOR 掩码,使数据报对被动观察者不可与随机串区分,并随机化 spoke 保活节奏。设 false 可关闭(改发可读的明文报头,例如抓包调试)。必须在网格内所有节点上设置一致(不协商;不一致则全部认证失败、fail-closed)。仅隐藏协议指纹,不隐藏包长或时序。

对端字段

peers[] 的每个条目:

字段类型默认说明
id整数对端网格 id(非零、u16)。用于派生方向链路密钥,并作为线上 key_id 选择器。
endpoint字符串对端承载地址,形如 host:port,例如 203.0.113.2:18020(使用对端 listen_ports 中的某个端口)。Hub 使用动态 DNS 时见部署指南
allowed_srcCIDR0.0.0.0/0允许该对端发送的内层源范围。解密后内层 IPv4 源落在范围之外的包被丢弃(spoof)。请显式设置——宽松的默认值会关闭反伪造。
psk十六进制串本链路的 私有 32 字节预共享密钥(64 个十六进制字符)。必填、非零、每链路唯一。用 openssl rand -hex 32 生成。
name字符串""可选的人类可读标签。过长或不可打印的值会被拒绝。

不存在全网 psk 每条链路携带自己的密钥。仍有顶层 psk 的配置以 InvalidPsk 拒绝;在多个对端间复用一把 PSK 以 DuplicatePsk 拒绝。

对端上限。 peers[] 的容量固定、零分配,由构建选项 -Dmax-peers 在编译期确定 (默认 32,上限 128);一个 hub 最多管理这么多 spoke,策略表大小随之伸缩。 见调整对端数量上限

防呆自检

config.zig 在加载时(以及 --check 下)执行这些检查;任何失败都中止启动:

  • MTU 区间: local_tun_mtu 必须为 68–1500。
  • 子网重叠: 虚拟子网不得与主机物理子网以会黑洞流量的方式冲突。
  • 网格 id: local_id 非零且与每个对端 id 不同。
  • 唯一 PSK: 没有 PSK 在对端间共享(DuplicatePsk);没有顶层 pskInvalidPsk)。
  • 角色规则(见 角色):
    • hub 拒绝 allowed_src 缺失/为 0.0.0.0/0 或与另一对端 allowed_src 重叠的对端。
    • spoke 要求恰好一个 Hub 对端、至少一个本地目标(local_routeslocal_tun_ip), 且没有 0.0.0.0/0 本地路由。

MTU 与线开销

固定的每包开销是 64 字节:20 字节私有报头 + 16 字节 AEAD tag + 28 字节外层 IPv4/UDP。 因此安全隧道 MTU 为 path_mtu − 64。默认 local_tun_mtu = 1452 假设 1500 字节承载。在更小 的路径上(PPPoE、VPN 承载),请调低它——主机网络规划 会为你计算并 告警

配置与文档其余部分的衔接