fix(speedtest): 端点 DNS 规则弃用 legacy strategy,拆掉与 query_type 共存即起核 FATAL 的隐患 - #334
Merged
Sway-Chan merged 1 commit intoJul 28, 2026
Merged
Conversation
…L 的隐患 测速临时 config 的端点目标解析规则用的是 sing-box rule-action 上的 legacy `strategy`。1.14.0 起该写法: 1. `sing-box run` 输出 deprecation 警告,1.16.0 移除(`check` 静默放行, 现有校验抓不到); 2. 与**同一份 DNS 配置内**任何带 `query_type` / `ip_version` 的规则(含引用 带 `query_type` 的 rule-set)**互斥**,共存即在 `initialize dns router` 阶段被拒——`check` 与 `run` 双双硬失败,代理直接起不来。 第 2 条此前只是恰好没踩上:主配置大量用 `query_type` 但 `strategy` 只出现在 顶层 `dns.strategy`(非 rule-action),测速配置有 rule-action `strategy` 却零 `query_type`。任一侧加一个字段就炸。 改用 `query_type` 规则项表达族别偏好,全仓不再有 rule-action `strategy`,该 组合结构性不可能出现: - 旧 `prefer_ipv4`(localAddress 含 v6)→ 不下发任何 strategy。测速 config 无 顶层 `dns.strategy`,内核默认并发 A/AAAA 且 v4 排前(`sortAddresses` 对 AsIS 与 prefer_ipv4 同一分支)。 - 旧 `ipv4_only`(纯 v4 localAddress)→ 该 inbound 的 AAAA 前置一条 `predefined` 空 NOERROR,AAAA 就地返空不出网,结果集只剩 A。 行为在随包核 1.14.0-beta.2 上逐观测实测等价(loopback 假 DNS + WireGuard endpoint,比对 deprecation 行、出网 qtype、解析结果与顺序):新旧两形态出网 查询类型一致、解析地址列表逐项同序;把 `generateProxyTestConfig` 的真实发射物 过核,`check` exit=0、`run` 零 deprecation,而改回旧形态即复现警告、旧形态再 加一条 `query_type` 规则即 FATAL 起不来。 抑制规则必须排在同 inbound 的 route(catch-all)规则之前,否则 AAAA 先被 route 吃掉、抑制静默失效且配置照样通过校验——已用变异实跑坐实,单测显式锁顺序。 唯一不等价点:legacy rule-action `strategy` 能覆盖顶层 `dns.strategy`,新写法 不能。测速 config 从不下发顶层 `dns.strategy`,故无影响;该前提已由单测和源码 注释锁死。 单测用 `toEqual` 锁精确形状,并覆盖:两档规则组、规则顺序、多端点互不串扰、 禁止 rule-action `strategy` 复活(配 query_type 存在性前置断言防空集平凡通过)、 禁止顶层 `dns.strategy`。六个变异(删抑制规则 / 条件反转 / strategy 复活 / 键名 typo / 偷加顶层 strategy / 顺序颠倒)逐个实跑转红。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
问题
测速临时 config(
SpeedTestService.generateProxyTestConfig)里端点(WG/WARP 等 L3)目标域名解析用的dns.rules[],把族别偏好写在 rule-action 的strategy上。sing-box 1.14.0 起这是 legacy 写法:sing-box run输出 deprecation 警告,1.16.0 移除。sing-box check静默放行(实测 exit=0)——现有的配置校验抓不到它。query_type/ip_version的规则(含引用带query_type的 rule-set)互斥,共存则在initialize dns router阶段被直接拒绝,check与run双双硬失败,代理起不来。第 2 条此前只是恰好没踩上,不是设计:主配置(
singbox-dns-builder.ts)大量用query_type: ['A','AAAA'],但strategy只出现在顶层dns.strategy(非 rule-action);测速配置有 rule-actionstrategy却零query_type。任一侧加一个字段就炸。改动
改用
query_type规则项表达族别偏好,FlowZ 全仓不再有 rule-actionstrategy,上述组合结构性不可能出现——埋雷是拆除,不是缓解。等价性依据(核源码 + 实测双证):
prefer_ipv4≡ 什么都不写:dns/client.go的sortAddresses只对prefer_ipv6走 v6-first 分支,AsIS 与 prefer_ipv4 落同一分支(v4 在前);测速 config 无顶层dns.strategy→ 内核并发 A/AAAA 后 v4 排前。ipv4_only≡ AAAA 就地返空:predefined+rcode: NOERROR让该 inbound 的 AAAA 在核内直接返空、不出网,结果集只剩 A。query_type/ip_version在内部解析(WG/Tailscale endpoint 解自身目标地址、SOCKS4 等)上开始生效——1.14 之前这些字段只对客户端来的查询有效、内部解析静默忽略。正是这条变化让 rule-items 能替代 rule-action strategy。§5 的行为一字未改:端点目标解析仍经 inbound 键控规则定向到穿本节点隧道的 223.5.5.5(AliDNS ECS 按出口地理返 IP),
detour/disable_cache/ 单入站 / 代理路径全部零改动。实测(本机 loopback,零宿主网络;随包核
1.14.0-beta.2)装置:两台 loopback 假 DNS(A→
198.51.100.<n>、AAAA→2001:db8::<n>,按 listen port 区分被查的是哪台、逐条记 qtype),http inbound → WireGuard endpoint(gVisor 用户态、peer 指 127.0.0.1 死端口,无 TUN/netns/iptables),curl -x触发端点对probe.test的本地解析。观测三件:run 日志的 deprecation 行、假 DNS 收到的 qtype、核lookup succeed for probe.test: <addrs>(含顺序)。strategy: ipv4_only198.51.100.2strategy: prefer_ipv4198.51.100.2 2001:db8::2198.51.100.2 2001:db8::2= 与 v0b 逐项同序query_type:[AAAA] → predefined NOERROR+ route198.51.100.2= 与 v0 一致query_type规则checkexit=1 且 run FATAL(埋雷坐实)query_type规则198.51.100.2/198.51.100.3 2001:db8::3— per-inbound 隔离成立、无跨节点缓存污染真实发射物端到端复核(不是手搓 config):把
generateProxyTestConfig实际发射的双端点配置落盘,仅把 stub outbound 补成完整 WG endpoint、把 223.5.5.5 改指 loopback 假 DNS(确保零出网),其余逐字节原样过核:sing-box checksing-box runquery_type规则顺序不变量
抑制规则必须排在同 inbound 的 route 规则之前。route 规则是该 inbound 的 catch-all,DNS 规则先匹配先命中——顺序反了则 AAAA 先被 route 吃掉、抑制静默失效,而配置照样 check 过、照样启动(上表 v5 实跑坐实)。单测显式锁
indexOf(predefined) < indexOf(route)。语义差异(如实声明)
唯一不等价点:legacy rule-action
strategy能覆盖顶层dns.strategy,新写法不能——省略即回落顶层默认。实测量化:顶层dns.strategy: prefer_ipv6下,旧strategy: prefer_ipv4返198.51.100.2 2001:db8::2(v4 先),新写法返2001:db8::2 198.51.100.2(v6 先)。对 FlowZ 无影响:测速配置从不下发顶层
dns.strategy(dns只有servers+ 可选rules)。该前提已由单测expect('strategy' in cfg.dns).toBe(false)锁死 + 源码处显式注释;将来若要给测速配置加顶层 strategy,必须同时重新推导端点规则,不能只加一半。另一处需知(无实际差别):新写法下内核仍会发起 AAAA 查询,只是被
predefined就地返空、不出网;legacyipv4_only压根不发。对出网流量、解析结果、耗时均无差别,仅核内多一次规则匹配。测试
speed-test-endpoint-dns.test.ts用toEqual锁精确形状(非属性点检),覆盖两档规则组 / 规则顺序 / 多端点互不串扰 / 禁 rule-actionstrategy复活(配「确有 query_type」前置断言防空集平凡通过)/ 禁顶层dns.strategy。六个变异逐个实跑转红:删抑制规则、条件反转(v6 档发 v4 档不发)、
strategy复活、键名 typo(rcode→rcod,sing-box check对 rule 内未知键无牙)、偷加顶层dns.strategy、抑制规则与 route 顺序颠倒。gate 全绿:
gen-build-info+tsc -p tsconfig.main.json+tsc -p tsconfig.renderer.json双 0 错;jest 3515 passed / 6 skipped / 37 snapshots(235 suites);eslint 0 errors / 63 warnings(与现有基线一致,全部落在本 PR 未触碰的行)。补充:上游文档尚未发布
deprecation 消息指向的 anchor
#migrate-dns-rule-action-strategy-to-rule-items在上游testing分支docs/migration.md里不存在(1.14 仍 beta,该节未写)。本 PR 的新写法系用随包核实测定型 + 核源码(dns/router.goresolveLegacyDNSMode/lookupWithRules、dns/client.gosortAddresses)交叉验证,非照抄文档。