Clash DNS 配置字段详解:nameserver、fallback 与 DNS 劫持
逐项讲解 dns 段的 nameserver、fallback、fallback-filter 与 dns-hijack,说明 fake-ip 与 redir-host 的差异以及常见解析异常的排查顺序。
先区分 DNS 解析、请求接管与代理分流
Clash DNS 配置需要回答三个不同的问题:域名由谁解析、应用的 DNS 请求如何进入内核、连接最终走哪个出口。nameserver 选择上游解析器,tun.dns-hijack 接管符合条件的 DNS 流量,rules 则决定业务连接的出口。这三层有关联,但不能互相替代。
本文以当前使用 mihomo 内核的客户端为主要对象。旧版 Clash、不同分支及客户端的配置生成器可能支持不同字段;界面里的“DNS 覆写”也可能替换订阅中的整个 dns 段。排错时应查看客户端最终生成、实际交给内核的配置,而不只检查订阅编辑框。
- 内核 DNS:只有启用
dns.enable,内核才按该段配置提供解析服务。 - 系统 DNS:操作系统当前使用的解析入口;仅打开 HTTP 系统代理,不代表所有 DNS 请求都会进入内核。
- 代理规则:域名或 IP 命中哪条规则,决定直连或代理;使用某个地区的 DNS 不等于选择该地区的代理节点。
- 应用自带 DNS:浏览器的安全 DNS、应用内置 DoH 可能绕过系统的传统 DNS 设置。
“DNS 劫持”在这里指把指定 DNS 流量重定向到本机内核,不等于运营商篡改解析结果。是否接管成功,需要用查询与连接日志验证。
nameserver 与 default-nameserver:业务解析和引导解析
先建立一个可单独测试的 DNS 监听入口
下面是用于合并到现有 mihomo 配置的 DNS 片段,不是包含节点和规则的完整配置。监听地址限定为本机,端口使用 1053,避免直接与系统的 53 端口竞争。此时系统不会自动使用它,后文会先通过显式查询测试。
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
- https://doh.pub/dns-query
nameserver 是常规域名查询使用的上游列表,可以包含传统 DNS 地址、DoH(DNS over HTTPS)或内核支持的其他协议。列出两个地址并不是声明严格的“主用、备用”顺序,不应依赖列表顺序实现故障切换策略。
default-nameserver 主要用于解析 DNS 上游自身的域名。例如访问 https://dns.alidns.com/dns-query 之前,需要先知道 dns.alidns.com 的 IP。显式提供 IP 形式的引导解析器,可以避免“解析 DNS 服务器域名又依赖该服务器”的循环依赖。
节点域名解析与 DNS 出站要分开检查
mihomo 的 proxy-server-nameserver 可专门用于解析代理节点的服务器域名。若节点地址本身无法解析,业务域名的 DNS 再正常也无法建立代理连接。开启 respect-rules 让 DNS 上游连接遵循路由规则时,更应正确设置节点域名解析路径,避免解析器依赖代理、代理又依赖同一解析器。
不要为了排错一次加入所有高级字段。先确认所选 DoH 在当前网络能够完成连接,再增加按规则出站等设置。DoH 通常使用 TCP 443,但“使用 HTTPS”不自动意味着“经过代理”,实际路径仍由内核配置与路由条件决定。
fallback 与 fallback-filter:结果筛选,不是超时备用
fallback 容易被误解成只有主 DNS 超时才使用的备份列表。实际配置中,内核会结合 nameserver 与 fallback 查询,并依据 fallback-filter 判断采用哪一类结果。它既不是代理节点备用组,也不负责保证某个域名走代理。
以下片段演示显式筛选条件,需与前面的 dns 段合并,不能在文件里再写第二个同名顶层段。示例关闭 GeoIP 筛选,使用文档示例网段和一个指定域名说明判断方式;这些网段并非完整的异常地址清单。
fallback:
- https://cloudflare-dns.com/dns-query
fallback-filter:
geoip: false
ipcidr:
- 0.0.0.0/8
- 192.0.2.0/24
- 198.51.100.0/24
- 203.0.113.0/24
domain:
- '+.github.com'
| 字段 | 判断对象 | 配置含义 |
|---|---|---|
geoip | 常规解析结果的 IP 归属 | 启用 GeoIP 条件,依赖可用的地理数据。 |
geoip-code | GeoIP 国家或地区代码 | 启用 GeoIP 时,常规结果不符合指定地区条件会触发使用 fallback 结果。 |
ipcidr | 常规解析返回的 IP | 命中列出的网段时,采用 fallback 结果。 |
domain | 查询的域名 | 匹配的域名直接使用 fallback 侧的解析结果。 |
若使用 geoip: true 与 geoip-code: CN,含义并不是“国内网站直连”,而是基于解析 IP 的地理归属判断结果是否可采用。CDN 地址、地理数据更新和网络出口都可能影响判断;代理出口仍由规则决定。需要指定某个域名使用固定解析器时,nameserver-policy 通常比堆叠地理筛选条件更直观。
fallback 上游也必须能够连接。如果所选上游在当前网络超时,强制某些域名使用 fallback 只会扩大故障范围。应先单独验证上游可达性,再启用筛选。
fake-ip 与 redir-host:返回虚拟地址还是真实地址
fake-ip 依靠地址映射保留域名信息
fake-ip 模式下,内核可向应用返回 198.18.0.0/16 范围内的虚拟 IPv4 地址,并保存域名与虚拟地址的映射。应用随后访问该地址时,流量需要再次被送入同一个内核,内核才能恢复域名、匹配规则并建立真实连接。此网段位于保留的网络测试地址空间,不是网站的公网地址。
因此,查询得到 198.18.x.x 不代表 DNS 污染。真正需要排查的是:DNS 已交给内核,连接却从普通路由发出;或者切换客户端、清空映射后,系统仍缓存旧的虚拟地址。只接管 DNS、不接管后续连接,是 fake-ip 无法访问的常见原因。
redir-host 返回真实 IP,但仍需正确接管连接
redir-host 模式通常返回上游解析得到的真实 IP,不要求应用连接虚拟地址。它对部分依赖真实地址的程序更容易兼容,但域名与连接的关联会受缓存、共享 IP 等因素影响。该模式名称也不代表必须启用 Linux 的 REDIRECT 防火墙规则,更不等于自动完成透明代理。
- 使用 TUN 且希望保留域名规则匹配信息时,可先测试
fake-ip。 - 局域网发现、特定设备或游戏出现兼容问题时,优先定位具体域名,再评估
fake-ip-filter。 - 默认 blacklist 过滤模式下,加入
fake-ip-filter的域名不再获得虚拟地址;其他过滤模式的含义需按当前 mihomo 配置确认。 - 更换增强模式后,重新启动受影响的应用并清理 DNS 缓存,避免混用两种模式的旧结果。
dns.ipv6: false 控制内核 DNS 对 AAAA 查询的处理,不等于关闭系统所有 IPv6 连接。浏览器若使用自己的 DoH,或者应用缓存了 IPv6 地址,仍可能通过其他路径建立连接。
tun.dns-hijack:接管 53 端口的边界
dns-hijack 写在 tun 段内,不在 dns 段内。以下是 mihomo 的常见 TUN 片段;它会修改路由,远程服务器操作前应准备控制台或其他恢复方式。桌面客户端通常通过服务模式或授权助手管理 TUN 权限,不要在不清楚权限来源时重复启动第二个内核。
tun:
enable: true
stack: mixed
auto-route: true
auto-detect-interface: true
dns-hijack:
- any:53
- tcp://any:53
any:53 用于匹配进入 TUN 的 UDP 53 DNS 流量,tcp://any:53 补充 TCP 53。它们不是扫描或拦截整张网络的开关:流量首先需要经过 TUN,才能由内核处理。路由排除项、操作系统行为以及本地回环解析服务,都可能让部分请求不进入这条路径。
- DoH:通常走 HTTPS 的
443端口,不会因为配置any:53就变成内核 DNS 查询。 - DoT:通常走 TLS 的
853端口,也不属于传统 53 端口接管范围。 - Ubuntu 本地解析:
127.0.0.53常是 systemd-resolved 的本地存根地址,看到它不能直接判定 DNS 未接管。 - 局域网设备:本机启用 TUN 不会自动接管路由器或其他设备的 DNS,网关部署需要额外的转发与防火墙设计。
不要为解决本机 DNS 问题直接把监听地址改成 0.0.0.0:53 并开放公网访问。确实需要服务局域网时,应限定允许访问的网段,并分别检查 UDP、TCP 防火墙规则。
Ubuntu 排查顺序:监听、查询、接管、出口
第一步:确认实际配置与监听进程
纯命令行部署可对实际配置目录执行测试。以下路径按 /etc/mihomo/config.yaml 举例;使用桌面客户端时,应检查客户端提供的运行配置,不要以这份路径替代它的真实目录。
mihomo -t -d /etc/mihomo -f /etc/mihomo/config.yaml
sudo ss -lntup 'sport = :1053'
resolvectl status
配置测试主要发现语法与配置问题,不代表上游网络一定可达。ss 用于核对 1053 是否被正确进程监听;如果出现地址占用,先定位另一个 DNS 服务,不要盲目停止系统解析服务。
第二步:绕过系统解析器,直接测试内核
Ubuntu 的 dig 来自 dnsutils 软件包。先使用显式地址查询,区分“内核 DNS 本身失败”和“系统请求没有进入内核”。
dig @127.0.0.1 -p 1053 example.com A
dig @127.0.0.1 -p 1053 example.com A +tcp
dig @127.0.0.1 -p 1053 example.com AAAA
观察响应状态、回答记录和是否超时。fake-ip 模式下,A 查询可能只证明内核能够分配虚拟地址,并不充分证明真实上游解析成功;还需结合一次实际访问与日志确认。设置 dns.ipv6: false 时,AAAA 没有地址回答也未必是故障。
第三步:验证系统入口与业务连接
resolvectl query example.com
curl -I --connect-timeout 10 https://example.com
curl -I --connect-timeout 10 --proxy http://127.0.0.1:7890 https://example.com
最后一条假设现有配置的 mixed-port 是 7890,并通过显式 HTTP 代理建立 HTTPS 隧道;它不能单独证明系统 DNS 已被接管。第二条也可能受环境变量代理影响,比较结果前应检查终端环境。若显式代理能访问、普通应用却失败,重点检查系统代理覆盖范围、TUN 路由与应用自带 DNS。
第四步:清理缓存并逐项回退
sudo resolvectl flush-caches
清理 systemd-resolved 缓存后,退出并重新打开浏览器;浏览器自身的 DNS 缓存和现有连接池未必随系统一起清空。短时提高内核日志级别,观察 DNS 超时、节点域名解析失败及规则命中,然后恢复原来的日志级别。日志可能包含访问域名,分享前应删去订阅地址、认证信息与个人访问记录。
常见现象与最小修改原则
| 现象 | 优先检查 | 下一步操作 |
|---|---|---|
| 显式查询 1053 超时 | 监听地址、端口占用、内核是否启动 | 先查 ss 和运行日志,再检查上游连接。 |
| 得到 198.18 开头地址但打不开 | fake-ip 后续流量与映射 | 核对 TUN 路由,清缓存后重新连接。 |
| 只有指定域名失败 | fallback-filter、nameserver-policy、域名规则 | 临时撤销单个域名的特殊策略,比较日志。 |
| 节点列表存在但全部连接失败 | 节点域名解析与节点自身可达性 | 检查 proxy-server-nameserver 及节点连接错误。 |
| 只有浏览器表现不同 | 安全 DNS、扩展代理与浏览器缓存 | 临时统一解析路径,重启浏览器后复测。 |
| 订阅更新后故障复现 | 客户端覆写与生成配置 | 将修改放入客户端支持的持久覆写机制。 |
可靠的调整顺序是:先让一个 DNS 监听入口可查询,再验证一个上游可达,然后确认系统请求和业务连接进入内核,最后增加 fallback、按域名解析策略及 TUN 接管规则。每轮只修改一个变量,并记录修改前后的查询结果。这样才能判断问题来自解析、路由还是节点,而不是把所有异常都归为“DNS 污染”。
需要了解端口、代理组与规则的整体关系,可继续阅读入门指南;核对配置字段时,可参照协议参考。本文中的 DNS 和 TUN 片段都应合并到已有配置,保留原有节点与规则,不要整份覆盖订阅。