mihomo DNS 配置详解:nameserver、fallback 与 fake-ip 劫持
逐项解释 dns 段里 nameserver、fallback、fallback-filter、enhanced-mode 与 DNS 劫持的作用,并给出常见场景的配置示例。
先区分 DNS 上游、应答模式与请求接管
mihomo 的 DNS 配置分为三个层次:请求由谁接收、向哪个上游查询、向应用返回什么地址。nameserver 与 fallback 负责上游解析;enhanced-mode 决定使用真实地址还是 fake-ip 映射;tun.dns-hijack 则负责把匹配的 DNS 流量送入内置解析器。这三层互相关联,但不能互相替代。
只在配置文件里写入 DNS 地址,并不代表浏览器已经使用它。系统仍可能查询路由器,浏览器也可能通过自己的 DoH 发起加密解析。排查时应先确认请求有没有进入 mihomo,再讨论上游是否可用。
| 配置项 | 主要作用 | 容易混淆的边界 |
|---|---|---|
dns.listen | 提供本地 DNS 监听地址 | 不会自动修改系统 DNS |
nameserver | 配置默认解析上游 | 不是代理节点列表 |
fallback | 提供参与结果筛选的另一组上游 | 不只是主上游超时后的重试服务器 |
fallback-filter | 按域名或解析地址筛选结果 | 不直接决定网页连接走哪个节点 |
enhanced-mode | 选择 fake-ip 或 redir-host | 不等于开启 TUN |
tun.dns-hijack | 接管匹配的 DNS 请求 | 不能直接解密任意 DoH 或 DoT |
nameserver 与 default-nameserver:解析上游和引导解析
nameserver 是默认使用的 DNS 上游列表。地址可以采用普通 DNS、DoH 等受支持格式。普通 DNS 示例是 223.5.5.5,DoH 示例是 https://dns.alidns.com/dns-query。DoH 加密的是到解析服务器之间的查询传输,并不自动保证应用连接使用代理。
为什么还需要 default-nameserver
当上游地址使用域名时,内核需要先知道该服务器的 IP。例如连接 dns.alidns.com 之前,需要完成它自身的域名解析。default-nameserver 用于这类引导解析;采用明确的 IP 地址可避免“解析 DNS 服务器还要先访问同一个 DNS 服务器”的循环。
dns:
enable: true
listen: 127.0.0.1:1053
ipv6: false
enhanced-mode: redir-host
default-nameserver:
- 223.5.5.5
- 119.29.29.29
nameserver:
- https://dns.alidns.com/dns-query
- https://doh.pub/dns-query
127.0.0.1:1053只向本机提供服务,不会把 DNS 服务暴露给局域网设备。redir-host向应用返回真实解析地址,适合作为第一轮连通性检查的基线。ipv6: false让内置 DNS 对 AAAA 查询返回空结果,不等于关闭操作系统 IPv6,也不阻止应用直接连接已有的 IPv6 地址。- 列表中写入多个上游,不应被理解为“严格按从上到下的顺序逐个尝试”。不要依赖排列顺序实现域名分流。
以上是独立的 dns 配置示例,不包含节点和代理规则。应把它合并进现有配置,而不是用它替换整份订阅。若网络屏蔽某个解析服务,需要换成当前网络实际可达的上游。
fallback 与 fallback-filter:按结果筛选,不是简单备用
fallback 的名称容易让人误以为它只在 nameserver 故障时工作。实际上,配置 fallback 后,内核可以向两组上游并发查询,再结合 fallback-filter 判断使用哪一侧的结果。因此,正常访问时看到 fallback 查询,并不一定表示主上游已经失败。
常见策略是让主上游处理本地网络适用的解析结果;当域名被指定使用 fallback,或主上游返回的地址不符合筛选条件时,采用 fallback 的解析结果。这个过程处理的是 DNS 应答选择,后续连接仍要经过代理规则匹配。
带 GeoIP 与地址范围筛选的示例
dns:
enable: true
listen: 127.0.0.1:1053
ipv6: false
enhanced-mode: redir-host
default-nameserver:
- 223.5.5.5
- 119.29.29.29
nameserver:
- https://dns.alidns.com/dns-query
fallback:
- https://dns.google/dns-query
- https://cloudflare-dns.com/dns-query
fallback-filter:
geoip: true
geoip-code: CN
ipcidr:
- 240.0.0.0/4
domain:
- '+.google.com'
geoip: true与geoip-code: CN配合,用 GeoIP 数据判断主上游返回的地址是否属于指定地区;不符合时倾向采用 fallback 结果。ipcidr列表匹配到主上游返回的地址时,会触发使用 fallback。示例中的240.0.0.0/4是地址筛选条件,不是节点网段或 TUN 地址池。domain中匹配的域名直接使用 fallback 解析结果;+.google.com表示匹配该域及其子域。- GeoIP 判断依赖内核使用的数据。数据库过旧、CDN 跨区域部署,都可能让实际选择偏离预期。
不要把所有私网地址都当作污染结果。企业内网域名返回 10.0.0.0/8、家庭设备返回 192.168.0.0/16 都可能正常。将这些范围全部加入 ipcidr,反而会让内部域名被送去公网解析。对于明确的内网域名,应优先考虑定向解析,而不是扩大 fallback 筛选范围。
fake-ip 与 redir-host:返回映射地址还是实际地址
enhanced-mode: fake-ip 会为域名分配池内的映射地址。应用收到地址后发起连接,流量进入 mihomo,内核再通过映射恢复域名并匹配规则。这样可以减少对应用侧真实 IP 解析的依赖,但前提是这些连接确实被内核接管。
redir-host 则返回真实解析地址,并维护相关域名信息。它更接近常规 DNS 行为;但域名与地址不一定是一对一关系,连接中的域名识别还会受到接管方式、缓存与嗅探配置影响。两种模式都不能替代正确的代理规则。
dns:
enable: true
listen: 127.0.0.1:1053
ipv6: false
enhanced-mode: fake-ip
fake-ip-range: 198.18.0.1/16
fake-ip-filter:
- localhost
- '*.lan'
- '*.local'
default-nameserver:
- 223.5.5.5
- 119.29.29.29
nameserver:
- https://dns.alidns.com/dns-query
- https://doh.pub/dns-query
fake-ip-filter 该放哪些域名
在通常的黑名单过滤模式下,fake-ip-filter 中匹配的域名不分配 fake-ip,而是返回真实地址。示例用于说明本机及局域网名称的例外处理;若配置另外设置了 fake-ip-filter-mode,需要先核对过滤模式,不能直接套用这里的含义。
- 局域网设备发现、部分游戏或需要真实 IP 的应用,可以按具体域名增加例外,避免直接加入过宽的通配规则。
- 过滤只改变应答方式,不会自动把
printer.lan交给路由器。内网名称仍需要能解析它的本地上游。 .local经常涉及 mDNS。把它加入过滤列表,并不代表 mihomo 会代理组播发现或自动修复投屏。- 不要因为看到
198.18.x.x就判定解析被污染。在该示例中,这是预期的 fake-ip 应答;真正的验证点是连接能否进入内核并恢复域名。
从 fake-ip 切换到 redir-host,或反向切换后,应清理系统 DNS 缓存并重启用于测试的应用。旧映射地址若仍被浏览器缓存,可能出现配置已经改动、连接却继续使用旧地址的现象。
TUN DNS 劫持:把 53 端口请求交给内置解析器
“fake-ip 劫持”通常混合了两个概念:fake-ip 是应答模式,DNS 劫持是请求重定向。下面的顶层 tun 片段可与前面的一个 dns 示例合并,接管进入 TUN 且符合条件的 UDP、TCP 53 端口请求。
tun:
enable: true
stack: mixed
auto-route: true
auto-detect-interface: true
dns-hijack:
- any:53
- tcp://any:53
any:53 用于 UDP DNS,tcp://any:53 用于 TCP DNS。这里的 53 是被匹配流量的目标端口;前文 dns.listen 的 1053 是本地测试监听端口,两者不需要写成相同值。内核将匹配请求交给内置 DNS,不是要求系统先直接访问 1053。
开启后仍可能绕过的流量
- 浏览器 DoH:通常走 HTTPS 443 端口,不属于普通 53 端口查询。诊断期间可暂时关闭浏览器的安全 DNS,测试结束后再按实际需求恢复。
- 应用内置 DoT:常见目标端口是 853。仅写入上述两条规则不会将其转换成内置 DNS 查询。
- 未进入 TUN 的流量:路由排除、其他 VPN、网卡选择和平台限制,都可能使请求绕开接管路径。
- 局域网设备:电脑开启 TUN 不等于成为全网 DNS 网关。其他设备的网关、DNS 和转发路径需要分别设置。
只有系统代理时,浏览器的 HTTP 请求可能已经走代理,但系统 DNS 仍由路由器处理。这不是 dns.enable 失效,而是请求没有送入内置解析器。需要按使用方式选择系统 DNS 指向、TUN 接管或其他明确的重定向方案。
内网定向解析与代理节点域名解析
家庭 NAS、公司内部服务与公网域名通常不适合共用同一套解析路径。mihomo 的 nameserver-policy 可以按域名指定上游,其选择优先于一般的 nameserver、fallback 组合。下面片段应合并到已有 dns 下,示例假定路由器地址确实为 192.168.1.1。
nameserver-policy:
'+.home.arpa':
- 192.168.1.1
proxy-server-nameserver:
- https://dns.alidns.com/dns-query
home.arpa 用于家庭网络本地域名。若路由器没有配置对应记录,写入策略也不会凭空生成解析结果。使用 fake-ip 时,如应用必须获得真实内网地址,还应把该域名加入适当的 fake-ip 过滤规则。
proxy-server-nameserver 用于解析代理节点服务器自身的域名,不负责所有代理网站的域名。为节点提供可直达的解析入口,可以降低“DNS 上游依赖代理,而代理又依赖 DNS 才能连接”的循环风险。
需要 DNS 遵循代理规则时
respect-rules: true 可让 DNS 上游连接遵循路由规则;使用时应同时配置 proxy-server-nameserver,并检查规则最终选择。它不是解决解析失败的通用开关。如果节点域名解析、上游连接和规则选择相互依赖,即使每个地址单独看都正确,整体仍可能无法启动。
按监听、解析、接管、规则四步验证配置
排查时保留一份可回滚配置,每次只修改一个层次。先使用 redir-host 验证真实解析,再测试 fake-ip,最后增加 fallback 或 DNS 出站规则,比同时启用所有功能更容易定位错误。
第一步:确认 YAML 已被加载
- 同一级只保留一个
dns:。重复键可能报错,也可能导致前一段被后一段覆盖。 - 缩进使用空格,不使用 Tab;
tun:与dns:是同级键,不能把整个 TUN 段缩进进 DNS。 - 订阅更新可能覆盖本地修改。长期设置应放入客户端支持的覆写机制,并在更新后检查最终生成配置。
第二步:直接查询本地 1053 端口
在提供 dig 的 macOS 或 Linux 环境,可执行下面两条命令,分别测试 UDP 与 TCP。若系统没有该工具,先使用相应系统的软件管理方式安装,或换用支持指定 DNS 端口的查询工具。
dig @127.0.0.1 -p 1053 example.com A
dig @127.0.0.1 -p 1053 example.com A +tcp
redir-host 模式应返回实际解析结果;fake-ip 模式下,未被过滤的域名通常返回配置地址池中的映射地址。若两条命令都超时,先检查 1053 监听、配置加载和本地防火墙,而不是立即修改代理规则。若返回 SERVFAIL,再结合日志检查引导解析、上游连接和证书验证问题。
第三步:检查系统查询是否进入内核
在 Windows 使用 ipconfig /flushdns 清理系统 DNS 缓存;使用 systemd-resolved 的 Linux 可执行 resolvectl flush-caches。随后关闭测试浏览器再打开,以减少应用自身缓存的干扰。直接查询 1053 成功、普通应用访问失败时,重点检查 TUN 路由和应用独立 DNS。
第四步:区分 DNS 成功与连接成功
查看客户端连接记录中的目标域名、匹配规则、出站策略与错误日志。DNS 返回地址只说明解析阶段完成;节点不可达、规则把目标送入错误出口、目标端口被拦截,都会造成网页打不开。fake-ip 地址能够被映射回域名,也不代表所选代理节点一定可用。
需要继续检查系统代理、端口或 TUN 环境,可查看故障排查;首次导入订阅与切换模式的操作顺序见配置教程。DNS 设置应服务于当前网络路径,而不是简单叠加更多解析服务器。