Skip to content

[control-plane] policy add --action forward 未强制 --target:缺失时静默落为 target=0(LOCAL_TARGET 本地交付),与 docs/CONTROL-PROTOCOL.md「required for forward」不一致 #170

Description

@jamiesun

背景

#169 新增的 docs/CONTROL-PROTOCOL.md(v1 控制面协议)§3.1 将 --target 描述为 forward 动作的必填项

--target — required for forward: the destination peer id (the id of a configured peer). Ignored for drop.

但守护进程的命令解析器 parseCommandsrc/uds.zig并不强制 --target。当 --action forward 而缺失 --target 时,PolicyEntry.target 取结构体默认值 0,而 0 == LOCAL_TARGET(本地 TUN 交付)。因此一条「本应转发到某 peer」的规则会被静默安装成「本地交付」规则;又因 policy add 是 fire-and-forget、无任何错误回包,调用方拿不到任何反馈。

证据(文件:行)

  • 文档断言:docs/CONTROL-PROTOCOL.md §3.1 "--target — required for forward"。
  • 解析器不校验 target:src/uds.zig:168-199 —— policy add 仅在 --src/--dst 缺失时返回 MissingArgument--action forward--target 不报错,直接返回 .policy_add
  • target 默认 0:src/policy.zig:20 target: u32 = 0
  • 0 即本地交付:src/policy.zig:76-80 pub const LOCAL_TARGET: u32 = 0;(注释:"A PolicyEntry.target of 0 is local delivery")。
  • peer id 必须非零:src/config.zig:298-300local_id/peer id 须非零且互不相同),故 0 不会是任何真实 peer,0 即 LOCAL_TARGET 这一语义无歧义。
  • applyAdd 不二次校验 target:src/uds.zig:654-665(仅检查容量后原样追加,不比对 peer 注册表)。
  • CLI 无二次校验:src/subnetra.zig:90 复用同一 parseCommand,故 subnetra CLI 同样不拦截(不会以 exit 2 退出)。
  • 回显可见:src/uds.zig:374-376 forward 规则序列化为 ... --action forward --target {d}policy show 会回显 --target 0

复现

对运行中的 daemon 发送(任意语言/CLI 均可,下面用 CLI):

subnetra policy add --src 10.0.0.0/24 --dst 10.0.1.0/24 --action forward
subnetra policy show
# 输出: policy add --src 10.0.0.0/24 --dst 10.0.1.0/24 --action forward --target 0

命中 10.0.1.0/24 的报文随后会被交付到本地 TUN(LOCAL_TARGET),而非转发到目标 peer。

预期 vs 实际

  • 预期(按文档「required」):缺 --target 的 forward 命令被拒绝(missing-argument / CLI exit 2),或文档明确说明守护进程不强制、缺省即本地交付。
  • 实际:命令被静默接受,安装成 target=0(本地交付)规则;无回包、无 CLI 报错。

影响范围

  • 直接影响 docs: control-plane protocol spec for cross-language integration #169 所定位的「跨语言集成方」:按文档以为 --target 是强校验项,构造 forward 规则时漏传/取值失败将得不到任何错误,却静默改变路由——本应转发的目的网段被本地交付,造成黑洞或误交付,且只能靠 policy show 事后发现 --target 0
  • 仅本机持有控制面权限者可触发;非安全越权,属健壮性/一致性问题。
  • 同时与本项目「malformed line 即静默丢弃」的既有约定不一致:此处不是被丢弃,而是被接受成另一种(本地交付)规则,比丢弃更易致误配。

建议(二选一)

  1. 代码侧(更贴合文档、更防误用,倾向此项):在 parseCommand 中,当 action == .forward 且未显式提供 --target 时返回 ParseError.MissingArgument(CLI 随即 exit 2,daemon 端按既有约定静默丢弃该行)。补一条解析单测覆盖 forward 缺 target
  2. 文档侧(若刻意保留隐式默认):修订 §3.1,明确守护进程不强制 --target,缺省 target=0 表示本地交付(LOCAL_TARGET),并提示用 policy show 复核。

倾向方案 1:与文档「required」表述一致,杜绝「应转发却静默本地交付」的隐性误配。

严重度

Low(功能一致性 / 健壮性;无安全越权)。


由每周架构与安全评审(自动化)发现 · 评审日期 2026-06-29 · 基线 commit de42f8f · zig build test 全绿。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

bugSomething isn't workingdocumentationImprovements or additions to documentation

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions