把问题拆成一条链路:应用发起 DNS 查询,Mihomo 接住 53 端口或系统 DNS,请求进入内置 DNS,enhanced-mode: fake-ip 返回虚拟地址,连接再用映射表还原域名,最后进入规则匹配。网页打不开、内网服务失效、规则组命中反常,通常是这 5 段里断了一段。

这篇只讨论 Mihomo / Clash Meta 内核的 fake-ip DNS 排错,不讨论订阅格式、客户端 UI 按钮,也不把所有现象都归到“网络不通”。测试基线按官方文档里的字段写:tun.dns-hijackdns.enhanced-modefake-ip-filterprofile.store-fake-iplog-level: debug

判断断在哪一段

先不要同时改 nameserver、规则集、TUN、系统 DNS。把现象归到下面一类,排查会快很多。

现象更可能断点看哪个字段验证信号
浏览器打不开,命令行工具正常浏览器 DoH 没走系统 DNSChrome / Firefox 安全 DNS 设置Mihomo 日志没有对应域名的 DNS 查询
所有域名都返回 198.18 段,但连接失败fake-ip 映射没有被连接阶段还原dns.enhanced-modeprofile.store-fake-ipdebug 日志有 DNS 分配,没有 connection rule match
内网域名、NAS、打印机后台打不开该域名被分配了 fake-ipfake-ip-filterfake-ip-filter-mode*.lan*.local 被返回真实内网地址
规则命中和预期不一致连接只剩 IP,域名上下文丢了DNS 接管入口、sniffer 设置日志能看到 rule match 用域名规则命中
重启后同一域名表现变了fake-ip 映射缓存丢失profile.store-fake-ip重启前后同域名映射变化被记录

官方 DNS 文档写明 enhanced-mode 可选 fake-ipredir-host,默认是 redir-host。所以排查 fake-ip 时,第一件事是确认配置最终生效后的值,而不是只看模板里有没有写过。

fake-ip 映射到底怎么工作?

fake-ip 不是把域名解析成真实服务器地址。它会先从 fake-ip-range 里分配一个虚拟 IPv4,常见是 198.18.0.0/16 这类测试网段;应用随后连接这个虚拟地址,Mihomo 再通过映射表找回原始域名。

这一层映射解释了两个常见误判:

  1. ping example.com 看到 198.18 段不代表解析坏了,反而可能说明 fake-ip 已经生效。
  2. 连接阶段如果没有进入 Mihomo,系统只会拿着 198.18 段直连,结果就是超时。

最小配置先长这样,排错时不要急着加入十几条上游 DNS:

profile:
  store-fake-ip: true

log-level: info

tun:
  enable: true
  dns-hijack:
    - any:53
    - tcp://any:53

dns:
  enable: true
  enhanced-mode: fake-ip
  fake-ip-range: 198.18.0.1/16
  nameserver:
    - https://doh.pub/dns-query
    - https://dns.alidns.com/dns-query
  fake-ip-filter:
    - +.lan
    - +.local
    - +.home.arpa

profile.store-fake-ip: true 的作用是把 fake-ip 映射表保存下来,下一次启动继续复用。排查“重启就坏”时,这个字段比反复换 DNS 更值得先看。

dns-hijack 没接住时会出现什么?

Mihomo TUN 文档里的 dns-hijack 示例是 any:53tcp://any:53。没有写协议时默认按 UDP 处理,所以很多配置会同时写 UDP 和 TCP 53。

它的作用是把命中的 DNS 连接导入 Mihomo 内置 DNS。换句话说,dns.enhanced-mode: fake-ip 写得再正确,请求没有进来,也不会产生 fake-ip 映射。

场景dns-hijack 能否接住排查动作
系统普通 UDP 53 查询通常可以看日志里是否出现域名查询
TCP 53 查询需要写 tcp://any:53少写时补上 TCP 入口
浏览器内置 DoH通常接不住关闭浏览器安全 DNS,或让浏览器使用系统 DNS
Android Private DNS文档提示会影响自动接管关闭 Private DNS 后再测同一域名
macOS / Windows 局域网 DNS文档提示不会自动捕获所有 LAN 查询单独检查系统 DNS 和客户端接管方式

如果你在公司网络、公共 Wi-Fi 或多设备环境里维护同一份 Mihomo 配置,DNS 接管是否完整比“换一个规则组”更关键。订阅本身还要能给 Clash / Mihomo / sing-box 这类客户端导出兼容格式;不想手工改多份客户端配置时,可以把 兼容 Clash / Singbox / V2Ray 的订阅 作为同一配置链路的上游来源之一,再用本文的日志方法验收。

浏览器 DoH 为什么会让 Mihomo 看不见域名?

Chrome、Firefox、Edge 都可能启用浏览器级安全 DNS。它们直接向 DoH 服务器发 HTTPS 请求时,Mihomo 的 dns-hijack: any:53 看不到传统 DNS 包,也就没有机会返回 fake-ip。

判断方法很简单:同一个域名,用系统工具查,再用浏览器打开。

工具期待看到什么如果不符合
nslookup example.com 127.0.0.1返回 fake-ip 或被过滤后的真实地址Mihomo DNS listen / 系统 DNS 没接上
浏览器访问 example.comMihomo 日志出现同域名 DNS 查询浏览器可能启用了 DoH
curl -v https://example.com日志有 DNS 和连接两段如果 curl 正常、浏览器异常,优先查浏览器 DNS

浏览器 DoH 排查不要只看页面错误码。更可靠的证据是:Mihomo debug 日志里有没有同一时间、同一域名的 DNS 查询记录。

fake-ip-filter 该放什么,不该放什么?

fake-ip-filter 的目标不是“越多越安全”,而是让不适合虚拟地址的域名返回真实地址。官方 DNS 文档还提供了 fake-ip-filter-modeblacklistwhitelistrule,默认是 blacklist

常见过滤对象如下:

域名类型建议原因
+.lan+.local+.home.arpa放入 fake-ip-filter局域网发现和设备后台通常需要真实内网地址
路由器、NAS、打印机自定义域名放入 fake-ip-filter避免后台被分配 198.18 段后无法连接
代理上游主机名结合配置决定,异常时优先放入GitHub issue 2740 讨论过 fake-ip 与 sniffing 组合下的回环风险
普通网站域名不建议大面积放入过滤太宽会让规则分流失去域名接管优势
广告或遥测域名交给规则处理不要用 DNS 过滤代替规则集维护

如果你启用了 sniffer.override-destination: true,还要额外注意上游主机名。2026 年 4 月的 MetaCubeX/mihomo issue 2740 讨论过一种坑:代理上游主机名没有排除在 fake-ip 外,嗅探改写目标后又被解析成 fake-ip,可能造成连接回环。这个 issue 不是官方确认的通用故障,但足够作为排障提醒。

规则匹配为什么会被 DNS 影响?

规则模式依赖连接阶段拿到足够上下文。fake-ip 模式下,Mihomo通过映射表把 198.18.x.x 还原成原始域名,然后域名规则、GEOSITE、RuleSet 才有机会命中。

如果映射丢了,连接阶段只看到一个虚拟 IP,表现会变成:

  • 域名规则没有命中,落到 MATCH
  • DOMAIN-SUFFIX 明明写了,日志却只显示 IP 规则。
  • 重启或热重载后,短时间内大量连接超时。

排查规则命中时,临时把日志拉到 debug:

log-level: debug

复现 30 到 60 秒就够了。debug 日志量很大,拿到证据后改回 info,否则桌面客户端和软路由都容易被日志刷屏。

cache 丢失时怎么确认?

fake-ip 的关键不是“某个域名永远对应同一个虚拟 IP”,而是连接发生时映射表还在。下面几类操作会让你误以为规则坏了:

操作可能影响记录什么
重启 Mihomo映射表重新加载或重建重启前后同域名返回值
关闭 store-fake-ip历史映射不再持久化配置变更时间和表现变化
热更新配置DNS 模块可能重载更新前后 60 秒日志
清理客户端缓存旧连接和新连接混杂关闭浏览器全部进程后重测

保守做法是:先启用 profile.store-fake-ip: true,再做一次完整复现。若重启前后同域名的 fake-ip 不同,只要连接阶段仍能还原域名,规则命中就不该受影响;真正的问题是“连接阶段找不到映射”。

用哪些日志确认已经修好?

排查 fake-ip DNS,不要只看“网页能打开”。至少留 4 类证据。

level=debug msg="[DNS] query example.com A from 127.0.0.1"
level=debug msg="[DNS] example.com --> 198.18.0.23"
level=debug msg="[TCP] 198.18.0.23:443 --> example.com:443"
level=info  msg="[Rule] DOMAIN-SUFFIX,example.com matched, proxy_group"

不同 Mihomo 前端的日志格式会略有差异,不要逐字匹配上面的示例。你要找的是四个信号:DNS 查询进来了、fake-ip 分配了、连接被还原成域名了、规则命中了。

只看到哪一段说明什么下一步
没有 DNS query请求没进 Mihomo查系统 DNS、浏览器 DoH、dns-hijack
有 DNS query,没有 fake-ipenhanced-mode 或 filter 生效方向不对enhanced-modefake-ip-filter-mode
有 fake-ip,没有连接还原连接没进 Mihomo 或映射丢失查 TUN、系统代理、store-fake-ip
有连接还原,没有规则命中规则写法或规则集加载问题查 RuleSet、GEOSITE、MATCH 顺序

最后把 log-level 改回 info,保留出问题前后的 30 到 60 秒日志、配置片段和测试命令。下一次再遇到同类问题,不必从头猜。

还可以对照哪些排查文?