Skip to content

luci-app-ssr-plus: set a nameserver for mihomo's built-in DNS - #2040

Open
gongdao123 wants to merge 1 commit into
fw876:devfrom
gongdao123:fix/mihomo-dns-reuse-tunnel-forward
Open

luci-app-ssr-plus: set a nameserver for mihomo's built-in DNS#2040
gongdao123 wants to merge 1 commit into
fw876:devfrom
gongdao123:fix/mihomo-dns-reuse-tunnel-forward

Conversation

@gongdao123

Copy link
Copy Markdown

修复 #2039

问题

DNS 解析方式为 mihomo 内置 DNS(pdnsd_enable=7)时,插件生成的 dns 段没有 nameserver。mihomo 的配置解析是「先套内置默认值,再用 YAML 覆盖」(config/config.go:604:612),所以缺失的键保留内置默认 —— v1.19.28 下是 https://doh.pub/dns-querytls://223.5.5.5:853。两者虽然加密,但都是国内递归解析器,无法正确解析被封锁的域名,结果指向伪造 IP,表现为间歇性 TLS 握手失败。

parseDNS 里的 len(cfg.NameServer) == 0 校验对非空默认值不触发,所以问题完全静默,日志无任何提示。

两条路径无条件受影响(都不写 dns.nameserver):

  • subscribe.lua:869 buildMihomoSubscribeYaml() —— 订阅聚合生成的「Mihomo 总节点」
  • clash_yaml.luabuild_tuic_runtime_doc / build_single_proxy_runtime_doc / build_shadowsocks_runtime_doc —— 单节点运行时配置

自带 dns: 段的机场 Clash 订阅不受影响。

改动

项目已有「反污染 DNS 服务器」配置项 tunnel_forward,其他每种 DNS 模式都读取它(dns2tcp init.d/shadowsocksr:166、chinadns-ng :1329、mosdns :1272、dns2socks),只有 mihomo 路径忽略。本 PR 让 mihomo 路径复用它:

  • build_dns_upstreams() —— 读 tunnel_forward,产出 nameserver / respect-rules / proxy-server-nameserver
  • build_dns_section() —— 收拢原先三处逐字重复的 dns 表,修掉单节点生成器路径
  • fill_missing_dns_upstreams() —— 在 merge()deep_merge 之后调用

respect-rules 让 DNS 查询跟随 rules 进入隧道,与 dns2tcp/dns2socks 为其他模式提供的语义一致(起作用的关键属性是在墙外完成解析,而非加密本身),并且不需要知道用户订阅中的策略组名称。

填充只在缺失时进行。 如果无条件写进 overlay,会因为 overlay 在 deep_merge 中优先而覆盖掉机场自带的 dns.nameserver,构成回归;放在 merge 之后按需填充可以避免,与已有的 fill_empty_proxy_groups 属同类处理。

对照 mihomo v1.19.28 源码确认

结论 出处
respect-rules 开启且未显式指定策略组时,查询跟随 rulesproxyName = dns.RespectRules config.go:1277-1278
respect-rules 要求 proxy-server-nameserver 非空,否则拒绝启动 config.go:1407-1408
proxy-server-nameserverrespectRules=false 解析,走直连,不会死锁 config.go:1437
udp://host:port 受支持,缺省端口 53 config.go:1219

第二条意味着两者必须成对写入,本 PR 始终如此。

测试

  • luac -p 语法检查通过
  • 从改动后的文件中抽取被测函数、stub 掉 uci / has_nonempty_sequence / get_filter_aaaa 后跑了 22 项断言,全部通过。覆盖:
    • dns 段缺失 / enable=false / 缺 nameserver / nameserver 为空表
    • 已有 nameserver 时保持原样不覆盖(回归防护)
    • 显式 respect-rules: false 不被改写
    • tunnel_forward 为空时回落默认、自定义值正确生效
    • build_dns_section()dns_mode7 / 非 7 时的 enable 取值
  • 环境:ImmortalWrt 25.12.1 r37978-cd0a06bfd3fd,Mihomo Meta v1.19.28

尚未在真机上跑过打包后的完整流程,如果需要我补真机验证结果请告知。

另外 issue 里问过、这里再提一下:enhanced-mode 硬编码为 redir-hoststrip_runtime_conflicts 会移除 fake-ip-range / fake-ip-filter,我按「刻意设计」处理,本 PR 不涉及 fake-ip。


🤖 Generated with Claude Code

When the DNS resolution mode is mihomo's built-in DNS (pdnsd_enable=7),
the generated dns section enables DNS but never sets any nameserver.
mihomo applies its defaults before patching them with the YAML, so the
absent key leaves the built-in nameserver list in place: doh.pub and
AliDNS over TLS. Both are encrypted, but both are domestic resolvers and
cannot resolve blocked domains correctly, so those domains end up
pointing at forged addresses and surface as intermittent TLS handshake
failures. Nothing is logged, because the "NameServer cannot be empty"
check never fires against a non-empty default.

Two config paths never set a nameserver at all: the aggregate node built
from a subscription (buildMihomoSubscribeYaml in subscribe.lua) and the
single-node runtime documents built here. A Clash subscription that
ships its own dns section is unaffected.

Every other DNS mode already honours the existing "Anti-pollution DNS
Server" option (tunnel_forward): dns2tcp, dns2socks, chinadns-ng and
mosdns all read it. Only the mihomo path ignored it. What makes those
modes work is not encryption but that the query is resolved outside the
censored network, which is what dns2tcp/dns2socks provide.

Reuse tunnel_forward as dns.nameserver and set respect-rules so the
query follows the routing rules into the tunnel. respect-rules requires
proxy-server-nameserver, so bootstrap it from the WAN-provided resolver
and fall back to a public resolver when none is available; mihomo parses
that list with respect-rules disabled, so the bootstrap cannot deadlock.

The merge path only fills what is missing, so a subscription that
already carries dns.nameserver keeps its own configuration untouched.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@zxlhhyccc

zxlhhyccc commented Aug 20, 2026

Copy link
Copy Markdown
Collaborator

@gongdao123 经测试,代理失败。

死锁过程:

  1. 你要访问 google.com
  2. respect-rules: true 要求 DNS 解析遵循路由规则
  3. google.com 匹配到国外策略组 → 走代理
  4. 走代理需要先连接节点(如 xxxx.com)
  5. 解析节点域名 xxxx.com 时,使用 proxy-server-nameserver
  6. proxy-server-nameserver 是 https://1.1.1.1/dns-query
  7. 访问 1.1.1.1 需要走代理(因为 1.1.1.1 是国外IP)
  8. 走代理需要先连接节点 → 又回到了步骤 4
  9. 死锁!永远无法完成解析

请按照mihomo的配置规则再核实一下。

@zxlhhyccc

zxlhhyccc commented Aug 22, 2026

Copy link
Copy Markdown
Collaborator

@gongdao123 我已经根据你的pr进行了修正,但是有一个问题,如果是二级路由,get_wan_nameserver函数获取的IP是上级路由的内网IP(即:网关,比如:192.168.2.1),该IP不能进行dns解析,会导致无法代理,只有一个办法,加入直连规则即可解决。

@gongdao123

Copy link
Copy Markdown
Author

理解了,我这边发现dns解析有问题是直接改的 clash 配置文件,所以想到反馈一下。

@zxlhhyccc

Copy link
Copy Markdown
Collaborator

@gongdao123 你的clash配置文件怎么改的?

@gongdao123

gongdao123 commented Aug 28, 2026

Copy link
Copy Markdown
Author

@zxlhhyccc z

我只加了这一段。

dns:
  nameserver:
    - https://1.1.1.1/dns-query#Proxy
    - https://8.8.8.8/dns-query#Proxy
  default-nameserver:
    - 223.5.5.5
    - 119.29.29.29
  proxy-server-nameserver:
    - https://223.5.5.5/dns-query
    - https://1.12.12.12/dns-query

@zxlhhyccc

Copy link
Copy Markdown
Collaborator

@gongdao123 不是你说的问题,我已经在修了,准备mihomo核心添加enhanced-mode: fake-ip(目前你的原始配置),待完善后你测试一下

@gongdao123

Copy link
Copy Markdown
Author

好的 没问题 @zxlhhyccc

@zxlhhyccc

Copy link
Copy Markdown
Collaborator

@gongdao123 因添加mihomo的fake_ip功能,最终提交的修改如无意外在本周末会提交,到时请您测试,另外,你发我的yaml节点是失效了吗?昨天都可以用来测试正常代理,今天咋不行?能否发一下最新的yaml文件?

@gongdao123

Copy link
Copy Markdown
Author

可以的,我怎么单发给你 @zxlhhyccc

@zxlhhyccc

zxlhhyccc commented Sep 4, 2026

Copy link
Copy Markdown
Collaborator

可以的,我怎么单发给你 @zxlhhyccc

@gongdao123 上次我发你了: zxlhhy@gmail.com

@gongdao123

Copy link
Copy Markdown
Author

已经发了,您看看。 @zxlhhyccc

@zxlhhyccc

Copy link
Copy Markdown
Collaborator

@gongdao123 好的,明天再验证一下,没有问题我就提PR了。

@zxlhhyccc

Copy link
Copy Markdown
Collaborator

@gongdao123 终于差不多搞定了,改动了很多地方,同时修了昨天存在的bug,明天提PR你能否测试一下,如没有问题我就合并。

@zxlhhyccc

Copy link
Copy Markdown
Collaborator

@gongdao123 已提交PR,请测试,结果请告知,谢谢!没问题我合并,目前我测试正常。见PR: #2043

@gongdao123

Copy link
Copy Markdown
Author

好的 我今天测试一下。

@zxlhhyccc

Copy link
Copy Markdown
Collaborator

好的 我今天测试一下。

@gongdao123 测试了吗?

@chobitsos

Copy link
Copy Markdown

好的 我今天测试一下。

如何了

@gongdao123

gongdao123 commented Sep 8, 2026

Copy link
Copy Markdown
Author

试过了,昨天反复试了几次。只要开了 fake ip, ssrplus 的服务就开不起来,关了就能开起来。 @zxlhhyccc
我一会儿让claude debug看看。

我订阅链接单发你,很容易复现。开 fake ip,服务就开不起来。日志看起来很正常。

2026-09-07 21:35:43: -----------end------------ 2026-09-07 21:35:40: 提示:Mihomo 托管节点不启用 SSR Plus 自动切换逻辑。 2026-09-07 21:35:38: ssr-rules: Using nftables 2026-09-07 21:35:38: gfw2ipset: Using nftables 2026-09-07 21:35:38: Main node: Mihomo v1.19.30 (Clash) Started! 2026-09-07 21:35:38: ssr-rules: Using nftables 2026-09-07 21:35:38: ssr-rules: Using nftables 2026-09-07 21:35:38: Clash 本地配置加载成功:/etc/ssrplus/clash/42f88073bb6c2ee80037b440bd46445b.mihomo.yaml (MD5: b23a64019085cc367935bc447ced15cc) 2026-09-07 21:35:38: ----------start------------ 2026-09-07 21:35:28 直连订阅: 已清理临时绕过规则数量: 2 2026-09-07 21:35:28: ssr-rules: Using nftables 2026-09-07 21:35:28: ssr-rules: Using nftables 2026-09-07 21:35:28 订阅更新成功 2026-09-07 21:35:28 新增节点数量: 1, 删除节点数量: 0 2026-09-07 21:35:28 维持当前主服务器节点。 2026-09-07 21:35:28 成功导入 Clash 总节点: Clash_mysub.cc_96de85a8 2026-09-07 21:35:28 new_md5: ca4f20a240a741e6b863af57c751db6f 2026-09-07 21:35:28 old_md5: 2026-09-07 21:35:28 groupHash: 96de85a8819842cafaee73f951d330bb 2026-09-07 21:35:28 处理订阅: https://mysub.cc/subscribe/28173/ie08Qp17ma/clash/ 2026-09-07 21:35:28 raw 长度: 296621 2026-09-07 21:35:26 读取到旧的 groupHash: nil 2026-09-07 21:35:26 直连订阅: 已添加临时绕过规则 -> nftables / pppoe-wan 2026-09-07 21:35:26 直连订阅: 已添加临时绕过规则 -> nftables / eth2 2026-09-07 21:35:26 订阅模式: Mihomo 总节点模式 2026-09-07 21:35:26 当前订阅模式: 不通过代理订阅

@gongdao123 gongdao123 closed this Sep 8, 2026
@gongdao123 gongdao123 reopened this Sep 8, 2026
@zxlhhyccc

Copy link
Copy Markdown
Collaborator

56f56ec

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.

3 participants