Skip to content

fix: 补齐 nat_output DNS 劫持保护 - #5223

Closed
eyaeya wants to merge 1 commit into
vernesong:devfrom
eyaeya:net/fw4-nat-output-dns-guard
Closed

eyaeya wants to merge 1 commit into
vernesong:devfrom
eyaeya:net/fw4-nat-output-dns-guard

Conversation

@eyaeya

@eyaeya eyaeya commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Dependency chain

推荐合并顺序:本 PR 建议在已合入的 #5209 之后评审。#5209 提供了按 chain/family 区分的 fw4_has_dns_hijack_rule,本 PR 只把这个能力用于仍未保护的 nat_output DNS 劫持调用点。

问题现象

在 fw4 + router_self_proxy=1 场景下,OpenClash restore/start 路径可能重复插入本机 nat_output DNS 劫持规则;如果 IPv6 dstnat 规则存在但 nat_output 规则缺失,当前代码也不会补回 IPv6 本机 DNS 劫持。

根因

#5209 已让 helper 能区分 dstnat / nat_output 和 IPv4 / IPv6,但调用点仍存在两个问题:

  • IPv4 nat_output 插入不检查 nat_output ipv4 是否已存在。
  • IPv6 nat_output 插入被包在 dstnat ipv6 guard 内,dstnat 已存在时会跳过整段,导致缺失的 nat_output 不能自愈。

证据

  • IPv4 enable_redirect_dns=1enable_redirect_dns=2 都会在 router_self_proxy=1 时插入 nat_output DNS 规则。
  • IPv6 原逻辑只在 ! fw4_has_dns_hijack_rule dstnat ipv6 成立时才进入 nat_output 插入。
  • reload "restore" 可不经过完整 firewall revert 直接重设部分规则,因此调用点需要自身幂等。
  • tests/fw4_dns_hijack_guard_test.sh 现有 helper 用例只能证明 helper 可区分 chain/family;本 PR 增加调用点检查,确保真实 nat_output DNS 插入前存在同 family guard。

修复方案

  • IPv4 两条 nat_output DNS 插入前增加 ! fw4_has_dns_hijack_rule nat_output ipv4
  • IPv6 把 nat_output DNS 插入从 dstnat ipv6 guard 内拆出,并单独使用 ! fw4_has_dns_hijack_rule nat_output ipv6
  • 保留原有 dstnatopenclash_dns_redirect、iptables/fw3 分支和 DNS redirect 语义。

为什么没有扩大修复范围

没有在本 PR 中重构 enable_redirect_dns=2openclash_dns_redirect 链刷新,也没有修改 fw3/iptables 路径。redirect chain 的重复规则和 jump 幂等属于另一个行为边界,需要单独评估 flush/guard 策略,避免把 DNS 转发语义和本机代理 DNS 劫持混在一个补丁里。

与已有开启态 PR 的关系

验证命令和结果

均已通过:

bash -n luci-app-openclash/root/usr/share/openclash/*.sh
bash -n luci-app-openclash/root/etc/init.d/openclash
bash -n tests/*.sh
tests/fw4_dns_hijack_guard_test.sh
for t in tests/*.sh; do "$t"; done
git diff --check
rg -n '^(<<<<<<<|=======|>>>>>>>)' luci-app-openclash/root/etc/init.d/openclash tests/fw4_dns_hijack_guard_test.sh

最后一条无命中。

剩余风险

未做 live router 验证。本 PR 不改变已有规则的端口或目标,如果用户在 restore 路径中同时切换 DNS redirect 模式/端口,仍依赖完整 firewall revert 或后续 redirect chain 幂等修复来刷新旧规则。

@eyaeya

eyaeya commented Jul 8, 2026

Copy link
Copy Markdown
Contributor Author

2026-07-08 最新上游覆盖复核与范围确认

本轮重新按最新 dev 复核后,结论是:上游已经合入了按 chain/family 区分的 fw4_has_dns_hijack_rule helper,但还没有覆盖本 PR 修复的真实 nat_output DNS 劫持调用点。因此本 PR 不关闭,也不需要做 merge conflict 修复;当前 GitHub 状态为 MERGEABLE/CLEAN

执行计划与复核结果:

  1. 先确认目标是否已由上游解决:helper 已在上游,但 IPv4 nat_output 插入点仍缺 guard,IPv6 nat_output 仍被 dstnat ipv6 guard 阻挡自愈。
  2. 只保留仍缺失的调用点修复:IPv4 两条本机 DNS 劫持插入前加 nat_output ipv4 guard;IPv6 将 nat_output 插入拆出并单独使用 nat_output ipv6 guard。
  3. 不重复实现上游已有 helper,不改 fw3/iptables 路径,不重构 openclash_dns_redirect 链刷新语义。

验证:

bash -n luci-app-openclash/root/usr/share/openclash/*.sh
bash -n luci-app-openclash/root/etc/init.d/openclash tests/fw4_dns_hijack_guard_test.sh
bash tests/fw4_dns_hijack_guard_test.sh
git diff --check origin/dev...HEAD
rg -n '^(<<<<<<<|=======|>>>>>>>)' luci-app-openclash/root/etc/init.d/openclash tests/fw4_dns_hijack_guard_test.sh

以上均通过。未做 live router 写入验证;本轮只做静态与聚焦脚本验证。

@eyaeya

eyaeya commented Jul 8, 2026

Copy link
Copy Markdown
Contributor Author

这个拆分 PR 已被新的合并版 PR 取代:#5229

原因:#5223#5226 都修改 fw4 DNS 劫持/redirect 相邻逻辑,并且按任意顺序合并都会在 luci-app-openclash/root/etc/init.d/openclashtests/fw4_dns_hijack_guard_test.sh 产生真实冲突。新的合并版 PR 保留了本 PR 的行为,同时把 nat_output guard 与 redirect jump guard 统一整理成单个 reviewer 友好的提交。

已在合并版 PR 中验证:

  • focused fw4 DNS guard test
  • init.d/openclash 语法检查
  • git diff --check
  • conflict marker scan
  • 多轮对抗式复核,最终无修改点

@eyaeya eyaeya closed this Jul 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant