TL;DR:先别改 Mihomo 规则。用终端确认设备实际拿到的 DNS,再看 dnsmasq 有没有把请求交给 Mihomo。OpenWrt/旁路由的 DNS 问题,十次里有六次出在 DHCP 和 IPv6 下发。
路由器上跑 Mihomo 时,用户常看到检测网站显示 DNS 来自运营商或某个公共 resolver,于是怀疑「Mihomo 没接管」。但 DNS 链路很长:终端、浏览器、DHCP、dnsmasq、Mihomo、上游 resolver,任何一层偏离都会产生类似结果。
先画清链路
理想链路通常是:
终端 → OpenWrt DNS(dnsmasq) → Mihomo DNS → 预期 resolver
旁路由常见错误链路:
终端 → 主路由 DNS → 运营商 DNS
终端 → IPv6 RDNSS → 公共 DNS
浏览器 → 内置 DoH → 外部 resolver
所以第一步必须在终端上看实际 DNS,而不是只看 OpenWrt 后台。
检查 DHCP 下发
Windows:
ipconfig /all
macOS:
scutil --dns | grep nameserver
Linux:
resolvectl dns
你希望看到的是 OpenWrt 或旁路由的 LAN 地址。如果这里已经是运营商 DNS、主路由地址或某个公共 DNS,那 Mihomo 配得再好也接不到请求。
旁路由场景要特别小心:主路由仍在发 DHCP 时,客户端可能根本不知道旁路由存在。要么让旁路由接管 DHCP,要么在主路由 DHCP 选项里把 DNS 指向旁路由。
dnsmasq 只保留一个出口
OpenWrt 的 dnsmasq 如果同时配置了多个上游,可能一部分请求走 Mihomo,一部分走默认 WAN DNS。排查时先收敛:
- DHCP 只下发路由器/旁路由地址。
- dnsmasq 上游只指向 Mihomo DNS 监听端口。
- Mihomo 再负责分流到不同 resolver。
这样日志最清楚。等链路稳定后,再考虑加备用 resolver。
fake-ip 与 redir-host 不要混用
fake-ip 会给域名分配虚拟地址,再通过路由表把连接关联回域名;redir-host 直接返回真实解析结果。两种模式混用时,缓存里可能同时存在虚拟 IP 和真实 IP,表现为某些设备正常、某些设备外跑。
排查建议:
- 先选一种模式,重启 Mihomo。
- 清空 dnsmasq 缓存。
- 让客户端断开 Wi-Fi 后重连。
- 再测 DNS 和目标域名连接。
IPv6 和浏览器 DoH
IPv6 是隐藏入口。OpenWrt 可能通过 RA/RDNSS 给客户端下发 IPv6 DNS,终端会优先用它。若你暂时不处理 IPv6,先关闭 LAN 侧 IPv6 DNS 下发;如果要保留 IPv6,就把 IPv6 DNS 也转进同一套 Mihomo 链路。
浏览器 DoH 也要检查:Chrome 的安全 DNS、Firefox 的 DNS over HTTPS、Android 的私人 DNS,都可能直接访问指定 resolver。排错阶段先关闭,确认基础链路没问题后再决定是否保留。
最小修复清单
| 层级 | 应做动作 |
|---|---|
| 终端 | 释放 DHCP 租约,确认 DNS 是路由器/旁路由 |
| DHCP | 只下发一个预期 DNS 地址 |
| dnsmasq | 上游指向 Mihomo DNS 端口 |
| Mihomo | 明确 fake-ip 或 redir-host,别混用 |
| IPv6 | 关闭 RDNSS 或纳入同一链路 |
| 浏览器 | 临时关闭 DoH,清缓存后复测 |
完成后再用 nslookup 或 dig 指定域名测试。不要只依赖网页检测,因为网页还会受到 CDN、浏览器缓存和 DoH 状态影响。