这篇按 2026-05-24 比对到的 OpenWrt、dnsmasq、Mihomo 和 sing-box 官方文档写,默认你用的是 OpenWrt 22.03 之后的 firewall4/nftables 思路。老 fw3 设备也能照着排查,但命令输出会不一样。
先不要同时改 DNS hijack、防火墙、客户端 TUN 和订阅配置。这个故障最容易误判,因为网页打不开、DNS 检测异常、Mihomo 日志没请求、sing-box FakeIP 不命中,都可能来自同一个入口冲突。
##把哪条链路定下来?
排查阶段只保留一条链路:
终端 -> OpenWrt LAN IP:53(dnsmasq) -> 127.0.0.1:7874(Mihomo 或 sing-box DNS) -> 上游 resolver
如果是旁路由,把「OpenWrt LAN IP」换成旁路由地址。关键不是谁当主角,而是同一台终端只能拿到一个预期 DNS 入口。
用终端先看真实下发值:
nslookup openwrt.lan
nslookup example.com
Windows 看:
ipconfig /all
macOS 看:
scutil --dns | grep nameserver
Linux 看:
resolvectl dns
你希望看到的是 OpenWrt 或旁路由 LAN 地址。这里如果已经出现主路由、公共 DNS、IPv6 地址或桌面客户端的虚拟 DNS,后面的 hijack 规则再漂亮也不算入口干净。
IPv6 为什么会偏离 IPv4 hijack?
OpenWrt 默认用 dnsmasq 处理 DNS/DHCP,用 odhcpd 处理 DHCPv6 和 RA。IPv4 DHCP 下发的 DNS 只解决一半问题,IPv6 侧还可能通过 RA/RDNSS 告诉客户端另一组 DNS。
典型现场是:你在 firewall 里接管了 TCP/UDP 53,IPv4 查询都进了 dnsmasq,但手机或 Windows 仍用 RDNSS 里的 IPv6 DNS 查 AAAA 记录。结果看起来像 DNS hijack 偶发失效。
排查时可以临时关闭 LAN 侧 IPv6 DNS 广播:
uci set dhcp.lan.dns_service="0"
uci set dhcp.lan.ra_dns="0"
uci commit dhcp
service odhcpd restart
这不是让所有人长期关闭 IPv6。它的作用是把变量减到一个:先证明问题是不是 RA/RDNSS 造成的。确认后,如果你需要 IPv6,就把 IPv6 DNS 也转回同一条 dnsmasq -> Mihomo/sing-box 链路。
旁路由和桌面客户端哪里会互相抢?
旁路由的常见错法是主路由仍在发 DHCP,桌面客户端又开了 TUN 或系统代理。结果同一台电脑同时收到三类指令:网关走主路由,DNS 走旁路由,应用连接又被本机客户端改路由。
用这张表定位冲突位置:
| 现象 | 更可能的冲突点 | 第一项检查 |
|---|---|---|
| 手机正常,电脑不正常 | 电脑本机客户端接管 DNS 或 DoH | 关闭桌面客户端 TUN/系统 DNS |
| IPv4 域名正常,IPv6 域名异常 | RA/RDNSS 下发了另一组 DNS | uci show dhcp.lan |
| Mihomo 没有 DNS 日志 | 请求没有到 Mihomo DNS listen | 终端实际 DNS 与 dnsmasq 上游 |
| sing-box FakeIP 不命中 | DNS 没走 sing-box 或反向映射缺失 | dns.servers、dns.rules、fakeip |
| 开启 hijack 后整网变慢 | dnsmasq 到本机 DNS 被再次接管 | 排除本机 DNS 服务地址 |
| 只重启后复发 | DHCP 租约或客户端缓存没刷新 | 释放租约并断开 Wi-Fi 重连 |
如果表里同时命中两项,处理更靠近终端的那一项。终端拿错 DNS 时,路由器内核再正确也接不到请求。
最小修复步骤
按下面顺序改,每一步只改一个变量:
- 选一台测试设备,关闭桌面 Mihomo、sing-box、Clash 系客户端的 TUN、系统 DNS 和 DoH。
- 在主路由 DHCP 页面确认网关和 DNS 下发值。旁路由方案里,DNS 只指向旁路由;主路由方案里,DNS 只指向主路由。
- 在 OpenWrt 上确认 dnsmasq 监听 53,Mihomo 或 sing-box 不直接抢 53。
- 让 dnsmasq 上游只指向一个本机端口,例如
127.0.0.1#7874。 - 临时关闭 RA/RDNSS DNS 下发,排除 IPv6 分支。
- 释放测试设备 DHCP 租约,断开 Wi-Fi 后重新连接。
- 用
nslookup、内核日志和浏览器各测一次同一域名。
Mihomo 监听示例:
dns:
enable: true
listen: 127.0.0.1:7874
enhanced-mode: fake-ip
ipv6: false
fake-ip-filter:
- "*.lan"
- "openwrt.lan"
sing-box 则不要只看 inbound。DNS 自己有 servers、rules、final、strategy 和 fakeip 字段;需要按域名路由时,再看 reverse_mapping 是否符合你的路由写法。
{
"dns": {
"servers": [],
"rules": [],
"final": "local",
"strategy": "prefer_ipv4",
"fakeip": {}
}
}
如果你的服务来源同时给 Mihomo、sing-box、V2Ray 多种导出,排障时可以用一份兼容 Clash / Singbox / V2Ray 的订阅做格式基线:路由器只导入路由器那份,桌面端只导入桌面端那份,不要把 JSON、YAML 和 URI 链接混着粘。
Mihomo 和 sing-box 的 DNS 要放在哪?
在 OpenWrt 上,推荐让 dnsmasq 继续站在最前面。原因很简单:它知道 DHCP 租约、本地域名、openwrt.lan、NAS、打印机和内网静态记录。
Mihomo 或 sing-box 更适合做后面的规则解析。它们负责 Fake-IP、规则匹配、上游 resolver、节点域名解析。让它们直接面对全 LAN 也能跑,但本地域名和 IPv6 例外会更难收拾。
推荐分工:
| 组件 | 保留职责 | 不建议承担 |
|---|---|---|
| dnsmasq | 53 入口、本地域名、DHCP 主机名、缓存 | 复杂代理规则 |
| odhcpd | DHCPv6、RA、RDNSS 下发控制 | 代替客户端 DNS 排错 |
| Mihomo DNS | Fake-IP、nameserver-policy、节点域名解析 | 直接抢 OpenWrt 53 端口 |
| sing-box DNS | DNS rules、final、strategy、fakeip | 和 Mihomo 同时接管同一入口 |
| 桌面客户端 | 单机调试、日志对照 | 排查阶段继续改系统 DNS |
如果你坚持让客户端直接问 Mihomo 或 sing-box DNS,至少要给 .lan、路由器管理域、NAS 和打印机写例外。否则内网服务会被送进外部 resolver 或 Fake-IP 池,表现为「网页能开,NAS 名字打不开」。
什么时候保留 DNS hijack?
DNS hijack 适合处理硬编码 53 端口的设备,例如电视盒子、IoT 设备、游戏主机或不方便改 DNS 的手机。它不是第一步,而是入口稳定后的补丁。
OpenWrt 官方示例用 firewall redirect 接管 LAN 到 53 的 TCP/UDP 请求,并建议用 nft list ruleset 和 uci show firewall 查运行态与持久配置。你要额外注意本机 DNS 服务的排除规则,避免 dnsmasq 发给 Mihomo/sing-box 的请求又被抓回 53。
排除逻辑可以按源地址或源 MAC 做。比如本机 DNS 服务在 192.168.2.2,就不要把它发出的 53 请求再次重定向。IPv6 也要单独看地址,不能只写 IPv4 规则。
怎么验收没有冲突?
验收不要换域名。用同一组样本看三层日志:
| 样本 | 终端结果 | OpenWrt 侧 | 内核侧 |
|---|---|---|---|
openwrt.lan | 返回路由器 LAN 地址 | dnsmasq 本地命中 | Mihomo/sing-box 不处理 |
nas.lan | 返回 NAS 内网地址 | DHCP/hosts 命中 | 不进入 Fake-IP |
| 普通公网域名 | DNS 服务器是 OpenWrt/旁路由 | dnsmasq 转发到本机端口 | Mihomo/sing-box 有 DNS 日志 |
| AAAA 查询 | 结果符合 IPv6 策略 | RA/RDNSS 不再给第二入口 | ipv6 或 strategy 行为可解释 |
| 硬编码 DNS 设备 | 仍被带回路由器 53 | firewall redirect 命中 | 没有循环日志 |
OpenWrt 上可以临时打开 dnsmasq 查询日志:
uci set dhcp.@dnsmasq[0].logqueries="1"
uci commit dhcp
service dnsmasq restart
logread -f | grep dnsmasq
看完记得关掉。DNS 查询日志量很大,长期打开会让路由器闪存和日志阅读都变得难受。
本文不覆盖什么
不处理 DoH/DoT 全量阻断,不讨论特定插件页面的按钮名。OpenClash、PassWall、homeproxy、ShellCrash 都包装了 Mihomo 或 sing-box,但底层冲突仍然回到 53 端口、DHCP、RA/RDNSS、Fake-IP 和桌面客户端接管。
不要用测速失败代替 DNS 链路排查。测速受策略组、目标站、UDP、TLS 和节点状态多重影响;DNS 排查只看请求怎么进、被谁解析、返回值对不对。