Clash Meta DNS 配置指南:你写的每一行都应该有理由
适用人群:在公司内网环境下使用 Clash Meta(mihomo)的研发同学
前置条件:了解基本的 DNS 概念(域名解析、DNS 服务器),有 Clash 基本使用经验
目标:读完之后能看懂自己的 DNS 配置,知道出问题时该改哪里
为什么要专门讲 DNS?
很多同学的 Clash 配置是从论坛、同事那里复制过来的。跑通了就用,出问题了不知道从哪里下手,改了一个地方又破坏了另一个地方。
DNS 是其中最容易被忽视、也最容易出问题的部分。它不是"选一个快的 DNS 服务器"这么简单——在 TUN 模式下,DNS 的配置直接决定了你写的路由规则能不能生效。
这篇文章的逻辑是:先讲清楚问题是什么,再说配置是怎么解决这个问题的。
一、TUN 模式下 DNS 为什么这么重要
正常情况下,DNS 很简单:应用问操作系统,操作系统问 DNS 服务器,返回 IP,建立连接。
但 Clash 的 TUN 模式把这个流程打破了。
TUN 会创建一个虚拟网卡,在网络层(IP 层)接管所有流量。问题在于,IP 层的数据包里只有目标 IP 地址,没有域名。等流量到达 TUN 的时候,域名已经消失了。
这就产生了一个矛盾:你的路由规则是按域名写的——
rules:
- DOMAIN-SUFFIX,github.com,LB Connect
- DOMAIN-SUFFIX,longbridge-inc.com,DIRECT但 Clash 收到的只是 140.82.114.4:443 这样一个 IP 地址。它根本不知道这个 IP 属于哪个域名,规则匹配无从谈起。
Clash 的 DNS 模块就是为了解决这个问题——通过在应用发出 DNS 查询时就介入,把域名留在 Clash 的视野里,后续才能做正确的路由决策。
二、fake-ip:用"假"换"快"
Clash 的 DNS 有两种工作模式,通过 enhanced-mode 控制。
redir-host 模式是直接解析。Clash 拿到域名,去真实解析,拿到真实 IP,再建立连接。逻辑简单,但每次连接都要等 DNS 解析完才能开始,延迟高。
fake-ip 模式是另一种思路:Clash 收到 DNS 查询时,立刻从一个保留地址段(198.18.0.0/16)里随机分配一个"假 IP"返回给应用。应用立刻开始连接这个假 IP,Clash 在后台拦截这个连接,查表知道"哦,198.18.0.5 对应的是 github.com",然后按规则路由出去。
效果是连接感知上更快,因为不需要等 DNS 解析完成。
enhanced-mode: fake-ip
fake-ip-range: '198.18.0.1/16'fake-ip 的副作用
fake-ip 的前提是 Clash 能拦截所有到这个假 IP 的连接。但有一类应用不走这套逻辑:
- NTP 时间同步:客户端解析到
time.windows.com的假 IP,直接去连接,期望对方是一个时间服务器——显然不是,时间同步静默失败 - 局域网设备发现:
192.168.1.1是你的路由器,198.18.x.x不是,发现不了 - Windows 网络检测:Windows 会定期 ping
www.msftconnecttest.com,拿到假 IP 后认为网络不通,状态栏显示"无网络访问"
这些问题的共同特征是:应用拿到 IP 之后,需要 IP 本身有特定含义,而不只是一个占位符。
解决方法是 fake-ip-filter——对这些域名的 DNS 查询,跳过 fake-ip,直接返回真实 IP。
fake-ip-filter-mode: blacklist # 默认所有域名走 fake-ip,以下例外
fake-ip-filter:
- '*.lan' # 局域网主机名
- '*.local' # mDNS 本地服务
- '*.arpa' # 反向 DNS,本质是 IP 查询
- 'time.*.com' # NTP 时间服务器
- 'ntp.*.com' # NTP 时间服务器
- '*.msftncsi.com' # Windows 网络检测
- 'www.msftconnecttest.com' # Windows 网络检测
- 'localhost.ptlogin2.qq.com' # QQ 本地鉴权实践建议:不需要一开始就把这个列表写得很全。碰到某个应用出现"连接看起来成功但功能不正常"的问题时,先怀疑是不是 fake-ip 干扰,确认后再加进来。
三、Sniffer:域名的第二次机会
fake-ip 解决了"快速返回"的问题,但还有另一个漏洞:不是所有流量都会经过 Clash 的 DNS 拦截。
有些应用把 DNS 结果缓存起来,重启后直接用缓存的 IP 建立连接,不发新的 DNS 查询。还有些应用直接硬编码 IP。在这些情况下,Clash 的 DNS 模块根本没有机会介入,它只看到一个 198.18.x.x 或者某个陌生 IP,域名信息完全丢失。
更关键的是:fake-ip 模式下所有假 IP 都在 198.18.0.0/16 段,这个地址段没有归属国,GEOIP 规则对它完全无效。
Sniffer 是补丁。它不从 DNS 层恢复域名,而是直接从流量的应用层协议里提取:
- TLS:握手阶段的 ClientHello 报文里有 SNI(Server Name Indication)字段,明文包含目标域名
- HTTP:每个请求的
Host头就是域名 - QUIC:和 TLS 类似,握手阶段包含域名信息
Clash 读取这些信息,把域名"还给"这条连接,之后的路由规则匹配才能正常工作。
sniffer:
enable: true
force-dns-mapping: true # 用 SNI 覆盖可能过时的 DNS 映射
parse-pure-ip: true # 对完全没有 DNS 记录的连接也尝试嗅探
override-destination: true
sniff:
TLS:
ports: [443, 8443]
HTTP:
ports: [80, 8080-8880]
QUIC:
ports: [443, 8443]⚠️ 在 fake-ip + TUN 模式下,不开 Sniffer 等于你写的域名规则只对一部分流量有效。 这是最常见的"规则明明写了但不生效"的根源。
四、DNS 查询的处理顺序
理解了上面三个概念之后,来看 DNS 查询在 Clash 内部是怎么流转的。
Clash 的 DNS 处理是一条三层流水线,按优先级从高到低:
收到 DNS 查询
│
▼
① nameserver-policy ← 最高优先级,按域名匹配,命中则直接返回
│
│ 未命中
▼
② nameserver ← 默认解析层,所有未被 policy 覆盖的查询
│
│ (如果配置了 fallback)
▼
③ fallback ← 与 nameserver 并发,根据 fallback-filter 决定用哪个结果关键点:
nameserver-policy命中后,nameserver和fallback都不会被调用fallback不是"nameserver 挂了的备用"——它是用来检测 DNS 污染的,两个并发,根据结果质量决定用哪个- 如果你把
nameserver-policy配置正确,fallback实际上没有用武之地
五、国内外域名分流:nameserver-policy
为什么需要分流
对国内域名用境外 DNS(比如 8.8.8.8):技术上能解析,但 CDN 会认为你在国外,返回海外节点的 IP,速度变慢。
对境外域名用国内 DNS(比如 223.5.5.5):国内公共 DNS 对被封锁的域名会返回错误结果(污染),用这些 IP 无法正常连接。
所以需要根据域名来源决定用哪个 DNS。nameserver-policy 就是干这个的。
nameserver-policy:
'geosite:cn,private':
- '223.5.5.5' # 阿里公共 DNS
- '119.29.29.29' # DNSPod
- 'https://doh.pub/dns-query' # DNSPod DoH(加密,备用)
- 'https://dns.alidns.com/dns-query' # 阿里 DoH(加密,备用)geosite:cn,private 是两个规则集的合并:
geosite:cn:社区维护的中国域名列表,包含百度、微信、淘宝等主流中国互联网服务geosite:private:私有/保留域名,包括*.local、*.lan、反向 DNS 等——这些绝不应该发送到公网 DNS
列表里配置多个 DNS 服务器时,Clash 并发查询,取最快返回的结果。
六、境外域名:让查询本身也走代理
未被 nameserver-policy 命中的域名落到 nameserver 处理,此时基本上全是境外域名。
对这些域名,有两个要求:
- 查询不能被污染:直接从国内网络问
8.8.8.8,ISP 可能对结果动手脚 - 查询不能泄露:DNS 查询明文包含你访问的每个域名,过 ISP 就等于全部暴露
解决方案是让 DNS 查询本身也走代理隧道。Clash 支持在 DNS 服务器地址后面加 # 来指定出口:
nameserver:
- 'https://8.8.8.8/dns-query#RULES' # 查询请求按路由规则走代理
- 'https://1.1.1.1/dns-query#RULES'#RULES 表示这个 DNS 查询本身也走 Clash 的路由规则。由于 8.8.8.8 和 1.1.1.1 是境外 IP,会命中代理规则,通过代理节点出去,到达 DNS 服务器时已经在墙外了,得到干净、真实的解析结果。
七、鸡生蛋问题:两个 Bootstrap 字段
这里有个循环依赖问题:
nameserver-policy配置了https://doh.pub/dns-query这样的 DoH 服务器,但 DoH 是 HTTPS,建立连接之前需要先解析doh.pub的 IP——谁来解析?- 代理节点配置的是域名(比如
lb-vmess-sg-01.taowiki.com),连接代理之前要先解析这个域名——但 DNS 配置要求走代理,这不是死循环?
Clash 为这两个问题各提供了一个专用字段。
default-nameserver:用于解析 DNS 服务器本身的域名(DoH 的 hostname)。它在整个 DNS 管道启动之前运行,所以必须是纯 IP 地址,不能是域名。
default-nameserver:
- '223.5.5.5' # 纯 IP,不需要被解析就能访问
- '119.29.29.29'proxy-server-nameserver:专门用于解析代理节点的域名。独立于主 DNS 管道运行,打破循环依赖。
proxy-server-nameserver:
- '223.5.5.5'
- '119.29.29.29'这两个字段存在的原因是一样的:有些 DNS 解析必须在主管道准备好之前完成,需要独立的出口。
八、直连流量的真实 IP 问题
fake-ip 模式下,应用拿到的 IP 是假的(198.18.x.x)。对于走代理的流量没问题——代理节点收到域名,自己去解析,返回结果。
但对于走 DIRECT 的流量,Clash 最终要建立一个真实的 TCP 连接,假 IP 没法用,必须重新解析一遍拿到真实 IP。
direct-nameserver 就是做这件事的:
direct-nameserver:
- '223.5.5.5'
- '119.29.29.29'流程大致是这样:
应用查询 longbridge-inc.com
→ Clash 立刻返回假 IP 198.18.0.x
→ 应用开始连接
→ 路由规则匹配:DIRECT
→ Clash 需要真实 IP → 用 direct-nameserver 重新解析 longbridge-inc.com
→ 拿到真实 IP,建立直连另外建议同时开启:
direct-nameserver-follow-policy: true这样直连重解析也遵循 nameserver-policy 的规则,国内域名用国内 DNS,行为前后一致。
九、fallback 该不该用
fallback 的设计初衷是:nameserver 对某些境外域名返回了被污染的结果(国内 IP),fallback 提供一个"参照组",如果两边结果差异大,就用 fallback 的结果。
但问题是:如果你已经用 nameserver-policy 把国内和境外域名分开了,境外查询走代理通道,根本没有被污染的机会,fallback 就没有存在的必要了。
两套方案同时用,会造成规则之间的干扰,而且很难调试。
正确做法是把 fallback 彻底关掉:
fallback: []
fallback-filter:
geoip: falsefallback: [] 让过滤器完全没有输入,geoip: false 则关掉 GeoIP 评估。两行同时写,确保 GUI 工具(比如 Clash Verge)不会偷偷把这些字段还原成有效值。
十、常见误区
误区一:配了代理就以为 DNS 也走代理了
很多同学以为配了代理节点,DNS 查询就自动走代理了。实际上,如果 nameserver 没有加 #RULES,DNS 查询还是从本地直接出去,会被污染。
误区二:不开 Sniffer,规则写了也白写
在 fake-ip + TUN 模式下,没有 Sniffer,所有流量到 Clash 眼里只是 198.18.x.x,域名规则根本无从匹配。DOMAIN-SUFFIX,github.com,LB Connect 这样的规则形同虚设。
误区三:fallback 和 nameserver-policy 混用
这两种方案都是为了解决"DNS 分流"问题,但实现思路完全不同。同时用反而让行为难以预测。选一个,用彻底。
误区四:IP-CIDR 规则没有加 no-resolve
fake-ip 模式下遇到 IP-CIDR 规则,如果没有 no-resolve,Clash 会尝试先做一次 DNS 解析再匹配。这是多余的,加上 no-resolve 跳过这步。
- 'IP-CIDR,192.168.0.0/16,DIRECT,no-resolve'
- 'GEOIP,CN,DIRECT,no-resolve'十一、完整的 DNS 配置参考
# ── Sniffer ──────────────────────────────────────────────────────────────────
# 从 TLS/HTTP/QUIC 握手中恢复域名,fake-ip + TUN 模式的必要配置
sniffer:
enable: true
force-dns-mapping: true # 用嗅探到的 SNI 覆盖可能过期的映射
parse-pure-ip: true # 对完全没有 DNS 记录的连接也嗅探
override-destination: true
sniff:
TLS:
ports: [443, 8443]
HTTP:
ports: [80, 8080-8880]
QUIC:
ports: [443, 8443]
# ── DNS ──────────────────────────────────────────────────────────────────────
dns:
enable: true
listen: ':53'
# fake-ip:立刻返回假 IP,连接不等 DNS,速度快
enhanced-mode: fake-ip
fake-ip-range: '198.18.0.1/16'
# 黑名单模式:以下域名不走 fake-ip,返回真实 IP
fake-ip-filter-mode: blacklist
fake-ip-filter:
- '*.lan'
- '*.local'
- '*.arpa'
- 'time.*.com'
- 'ntp.*.com'
- '+.market.xiaomi.com'
- 'localhost.ptlogin2.qq.com'
- '*.msftncsi.com'
- 'www.msftconnecttest.com'
# Bootstrap:用于解析 DoH 服务器的域名,必须是纯 IP
default-nameserver:
- '223.5.5.5'
- '119.29.29.29'
# 解析代理节点域名,独立于主 DNS 管道,避免循环依赖
proxy-server-nameserver:
- '223.5.5.5'
- '119.29.29.29'
# 最高优先级分流:国内 + 私有域名走国内 DNS
nameserver-policy:
'geosite:cn,private':
- '223.5.5.5'
- '119.29.29.29'
- 'https://doh.pub/dns-query'
- 'https://dns.alidns.com/dns-query'
# 兜底:境外域名,查询本身也走代理(#RULES)
nameserver:
- 'https://8.8.8.8/dns-query#RULES'
- 'https://1.1.1.1/dns-query#RULES'
# 直连流量重解析:fake-ip → 真实 IP
direct-nameserver:
- '223.5.5.5'
- '119.29.29.29'
direct-nameserver-follow-policy: true # 重解析也遵循 policy,行为一致
# fallback 关闭:nameserver-policy 已在源头分流,fallback 多余
fallback: []
fallback-filter:
geoip: false
prefer-h3: false
respect-rules: false
use-hosts: false
use-system-hosts: false
ipv6: false十二、配置决策速查
| 问题 | 对应配置 |
|---|---|
| 路由规则对 TUN 流量不生效 | 检查 sniffer 是否开启 |
| 连接快还是等 DNS? | enhanced-mode: fake-ip |
| 时间同步/局域网设备发现失败 | 把对应域名加入 fake-ip-filter |
| 国内域名走错 CDN,速度慢 | 配置 nameserver-policy 指向国内 DNS |
| 境外 DNS 被污染 | nameserver 加 #RULES,查询走代理 |
| 代理节点域名无法解析 | 配置 proxy-server-nameserver |
| 直连流量无法建立 | 配置 direct-nameserver |
| fallback 和 nameserver-policy 冲突 | 选其一,推荐 policy 方案,fallback: [] 关闭另一个 |
| IP 规则触发不必要的 DNS 解析 | 所有 IP-CIDR 和 GEOIP 规则加 no-resolve |
还没有评论
欢迎留下你的观点,保持交流的清晰和友好。
写下评论