mihomo DNS 配置详解:nameserver、fallback 与 DNS 劫持的写法
逐字段解释 dns 段的 enhanced-mode、nameserver、fallback、fallback-filter 与 dns-hijack,附可直接参考的分场景配置片段。
先确认 DNS 请求经过哪里
先区分“域名解析”和“连接转发”。DNS 是把域名转换为 IP 地址的查询过程;代理规则决定连接最终直连还是经过代理。解析成功不代表流量已经走代理,开启系统代理也不代表系统的全部 DNS 查询都进入了 mihomo。
再确认客户端使用的内核。mihomo 是 Clash Meta 更名后延续维护的内核,图形客户端负责生成配置、启动内核和管理系统网络。本文按 mihomo 的字段说明编写,不能把所有片段直接用于较早的原版 Clash。先在客户端的内核信息页查看版本,或运行下面的命令记录版本与配置检查结果。
mihomo -v
mihomo -t -f config.yaml
沿着下面的顺序检查。只修改发生问题的一层,比同时替换 DNS、节点和规则更容易找到原因。
- 应用发起查询:浏览器可能使用自身的安全 DNS,终端程序通常调用系统解析器。
- 请求进入解析器:请求可能到达路由器、系统 DNS,或 mihomo 的 DNS 监听端口。
- 内核选择上游:mihomo 根据解析策略选择 DNS 服务器,并按配置筛选回答。
- 应用建立连接:内核再按代理规则,为后续连接选择出口。
理解 dns 段:监听、模式与上游分开设置
先看字段各自负责什么。下表中的端口是本文示例值,不代表每个客户端的默认设置;应以当前运行配置为准。
| 字段 | 作用 | 检查重点 |
|---|---|---|
enable | 启用内核 DNS 模块 | 设为 true 后仍需让请求进入内核 |
listen | 开放 DNS 查询监听地址 | 127.0.0.1:1053 仅供本机访问 |
enhanced-mode | 选择增强解析模式 | 常用 fake-ip 或 redir-host |
default-nameserver | 解析 DNS 上游服务器本身的域名 | 用于启动解析链路,不等于所有业务域名的默认上游 |
nameserver | 配置常规解析上游 | 列表顺序不能简单理解为逐个故障切换 |
fallback | 提供参与备用结果选择的解析上游 | 不只是主上游超时后才工作的备用地址 |
fallback-filter | 决定何时采用备用解析结果 | 可结合域名、GeoIP 与 IP 网段判断 |
选择 fake-ip,还是 redir-host
先按兼容性需求选择模式。fake-ip 会给符合条件的查询分配虚拟地址,并在内核中保存域名映射。应用连接这个地址时,内核可以找回域名再处理连接。示例中的 198.18.0.1/16 是虚拟地址池设置,不是要配置到公网 DNS 中的服务器地址。
遇到需要真实解析地址的程序,再考虑针对域名添加 fake-ip-filter,或用 redir-host 做对照。后者返回真实解析地址。切换模式后应刷新系统与应用的 DNS 缓存、重启旧连接,否则程序可能继续使用切换前的地址,造成“配置没有生效”的错觉。
场景一:用最小配置验证 nameserver
先只启用一组上游,把 fallback 留到基础查询正常后再加。下面是一份独立的诊断配置,使用本机混合代理端口 7890 和 DNS 端口 1053。它没有订阅节点,末尾规则全部直连,目的是测试 DNS 链路,不是完整代理方案。
mixed-port: 7890
allow-lan: false
mode: rule
log-level: info
dns:
enable: true
listen: 127.0.0.1:1053
ipv6: false
enhanced-mode: fake-ip
fake-ip-range: 198.18.0.1/16
default-nameserver:
- 223.5.5.5
- 119.29.29.29
nameserver:
- https://dns.alidns.com/dns-query
rules:
- MATCH,DIRECT
保留现有订阅时,只合并这里的 dns 段,不要用示例的 rules 覆盖原来的分流规则。YAML 同一级不要出现两个 dns:,缩进使用空格。配置检查通过后,再用客户端重新加载内核配置。
解释 DoH 与启动解析
识别上游地址的协议。https://dns.alidns.com/dns-query 是 DoH,即通过 HTTPS 传输 DNS 查询;普通 IP 形式的上游通常使用传统 DNS。DoH 加密的是客户端与该解析服务之间的查询传输,不代表所有后续网站连接都经过代理。
先让上游服务器的域名能够解析,再谈业务域名。示例用 default-nameserver 中的 IP 地址为 DoH 服务器域名提供启动解析,避免“必须先访问 DoH,才能知道 DoH 地址”的循环。公共解析服务是否可达取决于当前网络,不能把某一条地址视为所有环境通用的答案。
场景二:配置 fallback 与 fallback-filter
先理解备用结果的选择逻辑,再添加服务器。配置 fallback 后,不能把它当成普通网络设备里的“第二 DNS”。常规与备用上游可能并行参与解析;是否采用备用结果,由过滤条件和解析状态等因素决定,不是简单等待第一个地址超时。
下面的片段用于替换上一份配置的整个 dns 段。它演示按 GeoIP 判断常规上游的结果,并把 240.0.0.0/4 列为需要改用备用结果的网段条件。
dns:
enable: true
listen: 127.0.0.1:1053
ipv6: false
enhanced-mode: fake-ip
fake-ip-range: 198.18.0.1/16
default-nameserver:
- 223.5.5.5
- 119.29.29.29
nameserver:
- https://dns.alidns.com/dns-query
fallback:
- https://cloudflare-dns.com/dns-query
fallback-filter:
geoip: true
geoip-code: CN
ipcidr:
- 240.0.0.0/4
逐项检查过滤条件
- 检查地区判断:
geoip: true启用 IP 归属地判断。geoip-code: CN表示常规结果不符合该地区条件时,会倾向采用备用结果。这不是“国内域名全部直连”的代理规则。 - 检查地址网段:
ipcidr是 IP 网段列表。常规上游返回的地址命中这些过滤网段时,会触发备用结果选择。不要随意把企业内网网段全部加入,否则可能破坏内部服务解析。 - 检查数据依赖:GeoIP 判断依赖可用的地理数据。数据缺失或过旧时,先解决内核日志中的加载问题,不要仅靠反复更换 DNS 服务器掩盖原因。
- 检查两条链路:备用 DoH 也必须可达。主上游能返回结果,并不能证明备用上游连接正常。
需要固定某些域名的解析上游时,优先研究 nameserver-policy 这种按域名指定解析器的机制,而不是不断扩大备用过滤网段。企业域名尤其应交给企业 DNS,否则公共解析器可能根本不知道内网记录。
分别检查 DNS 上游的连接出口与网站连接的出口。它们是两件事。需要让 DNS 上游连接遵守路由规则时,可进一步配置 respect-rules,并按当前内核要求配置 proxy-server-nameserver 来解析代理服务器域名,避免代理连接与 DNS 解析互相等待。本文的最小示例不启用这组进阶设置。
场景三:用 TUN 的 dns-hijack 接管 53 端口
先把字段放对层级。dns-hijack 属于顶层 tun 段,而不是 dns 段。TUN 是虚拟网络接口,内核通过它处理被路由进来的 IP 流量;DNS 劫持在这里指把符合条件的 DNS 请求重定向给内核 DNS 模块。
在现有配置中保留前面的 dns 段,再合并下面的 tun 段。启用前应确认客户端具备所需的管理员权限或服务权限,并避免让另一个 VPN 同时接管默认路由。
tun:
enable: true
stack: mixed
auto-route: true
auto-detect-interface: true
dns-hijack:
- any:53
- tcp://any:53
区分两条劫持规则。any:53 用于匹配被 TUN 接管的 UDP 53 查询;tcp://any:53 补充 TCP 53 查询。它们描述的是捕获目标,并不是要求把 DNS 监听地址改成 any:53。实际能否捕获还受系统路由、接口和平台限制影响。
明确接管范围
- 检查浏览器安全 DNS:浏览器自行使用的 DoH 通常走 HTTPS 端口 443,不会因为劫持了 53 端口就自动变成内核 DNS 查询。
- 检查加密 DNS:DoT 是通过 TLS 传输的 DNS,通常使用 853 端口,也不在上述两条规则的范围内。
- 检查局域网目标:指向路由器的 DNS 流量是否进入 TUN,取决于路由安排,不能假设所有局域网请求一定被捕获。
- 检查监听暴露:个人电脑测试优先使用回环监听。不要为了让 TUN 生效,就把 DNS 无条件开放到所有网卡。
按顺序验证解析、接管与规则
先测试内核监听,再测试日常访问。这样可以区分“DNS 模块本身没有响应”和“系统查询没有送进来”。以下命令只给出检查方法,不代表某个公共解析器在当前网络下的实测速度。
第一步:直接查询 1053 端口
在安装了 dig 的 Linux 或 macOS 环境运行下面两条命令,分别测试 UDP 和 TCP。Windows 可使用后面的 nslookup 命令指定端口。
dig @127.0.0.1 -p 1053 example.com A
dig @127.0.0.1 -p 1053 example.com A +tcp
nslookup -port=1053 example.com 127.0.0.1
先看是否超时,再看回答类型。启用 fake-ip 时,符合条件的 A 查询返回虚拟地址池中的地址属于正常现象,不能据此判断上游返回了错误 IP。需要对比真实解析时,可临时改为 redir-host、重载配置并清缓存,再做同一组查询。
第二步:通过系统默认路径查询
nslookup example.com
对比显式查询与默认查询。如果访问 1053 正常,默认查询却超时,应优先排查系统 DNS、TUN 路由和安全软件,而不是立即更换 nameserver。开启劫持后,命令显示的 DNS 服务器名称可能仍是原目标;应结合内核日志确认请求实际由谁处理。
第三步:刷新缓存,再检查连接出口
Windows 可运行 ipconfig /flushdns;使用 systemd-resolved 的 Linux 可运行 resolvectl flush-caches。随后重启浏览器或关闭旧连接,检查客户端连接面板中的域名、命中规则和出口。浏览器自身的缓存与连接复用,不一定随系统缓存一起清理。
需要更多线索时,临时把 log-level 改为 debug,重现一次故障后恢复为 info。分享日志前删除订阅地址、认证信息和敏感域名。日志可以帮助定位上游超时、监听失败和路由问题,但不应把完整运行配置直接公开。
常见故障:按现象缩小修改范围
| 现象 | 优先检查 | 下一步动作 |
|---|---|---|
| 本机 1053 查询超时 | DNS 是否启用、端口是否冲突、配置是否重载 | 检查启动日志,再运行配置语法检查 |
| 1053 正常,普通查询失败 | 系统 DNS 路径与 TUN 路由 | 确认请求是否进入内核,而不是先改备用上游 |
| 浏览器与终端结果不同 | 浏览器安全 DNS、各自缓存、代理扩展 | 临时统一解析路径,再查询相同域名 |
| 内网站点无法访问 | 公共 DNS 不含内部记录、虚拟地址兼容性 | 为内部域名指定企业解析器,必要时添加 fake-ip 过滤 |
| 启用 fallback 后查询变慢 | 备用上游连通性与过滤命中范围 | 回到单一上游基线,再逐项恢复过滤条件 |
| 订阅更新后设置恢复原状 | 客户端生成配置覆盖了手动修改 | 将改动移入受支持的覆写配置并核对最终结果 |
最后按三个问题收尾:请求是否进入内核,上游是否正确回答,后续连接是否命中预期规则。一次只改变一个条件,并保留修改前后的配置与查询结果。这样排查 nameserver、fallback 或 dns-hijack 时,才能知道是哪项设置真正解决了问题。