本篇文章着重记录Clash.meta/mihomo的DNS运行特点(如DNS缓存状况、fallback机制等),作为备忘录使用,后面提到的Clash均代表Clash.meta/mihomo。

乐观缓存

  • Clash的DNS拥有乐观缓存机制,测试时Clash提供了一个过期了24个小时的记录,其TTL为1(1秒),并且在提供过期记录之后触发了DNS解析,在下次解析时Clash返回了新获取的记录。
  • 根据配置文件,Clash应该没有持久化保存DNS缓存的机制,即在Clash重启或关闭后缓存就会丢失。
  • 乐观缓存目前是无法关闭的。

缓存算法 cache-algorithm

从名字可以看出cache-algorithm这个字段作用于DNS缓存中,不知道会不会和乐观缓存有关系。其可选值是lruarc,默认是lru

lru应该是指Least Recently Used(最近最少使用)作用大概是:在有限的缓存空间内尽可能的储存常用条目。
arc则是Adaptive Replacement Cache(自适应替换缓存)arc结合了lrc以及另一种lfu算法(Least Frequently Used,最近最不常用),arc能根据当前使用情况动态调整缓存空间大小,在判断常用条目上更智能和准确。

如果没出现什么问题个人建议使用arc算法。

Fallback

DNS的fallback组和nameserver组通常是并发解析的,即同时使用这两个组解析域名,这是为了防止DNS污染,这也是使用Clash时有DNS泄露的原因,并不是BUG或漏洞,这是正常现象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
dns:
# ...
fallback-filter:
geoip: true
geoip-code: CN
geosite:
- gfw
ipcidr:
- 240.0.0.0/4
domain:
- '+.google.com'
- '+.facebook.com'
- '+.youtube.com'
# ...

fallback-filter

  • 两组解析时,根据nameserver返回的结果以及fallback-filter的过滤规则决定选择哪一个组的结果。
    比如:在geoip-code为CN时,检查nameserver结果的IP地址是否属于CN,如果不属于则采用fallback组的结果。
    同理nameserver的结果如果在ipcidr字段中也会采用fallback组的结果。
  • ipcidrgeoip-code不同,domaingeosite不会等到两个组都解析出结果时才起作用,而是直接交给fallback组解析,完全不使用nameserver
  • 要注意这里的geosite字段已经被弃用,弃用的警告会在Clash启动时输出到日志中并且建议用户改用nameserver-policy
flowchart LR
  domain("域名")-->a{它的IP属于CN吗}
  a-->|属于|c("采用nameserver组的结果")
  a-->|不属于|b("采用fallback组的结果")

关于DNS增强模式(enhanced-mode)

文档中只提到了fake-ip与redir-host两种模式,但是在源码中除了这两种模式以外还有hosts以及normal,具体作用还不是很清楚。相关代码

Clash记录网络连接时会有一个dnsMode字段,它表明了此连接使用的DNS模式。根据OpenClash的issue#1819来看,normal模式则可能代表着使用了远程解析?而hosts模式可能在启用并匹配到hosts时才会显示。在启用了fake-ip时大部分连接为fake-ip,而在redir-host下大部分是normal,只有少部分是redir-host。另外即使用fake-ip-filter让某些连接不使用fake-ip后在连接的dnsMode中仍然是fake-ip,也许是一个小bug?

建议目前使用时只在fake-ip与redir-host之间二选一,毕竟文档中没有提到其他模式。

Fake-ip

  • 使用Fake-ip响应DNS解析时Clash不会在日志中显示解析记录。
  • 有些互联网连接不支持使用Fake-ip,所以需要配置fake-ip-filter将这些连接切换为普通的真ip模式(redir-host)。

fake-ip-filter和fake-ip-filter-mode

fake-ip-filter用于指定哪些域名需要使用fake-ip,它根据fake-ip-filter-mode的值来决定使用白名单还是黑名单模式,默认是黑名单模式。

  • 白名单模式下(whitelist),在fake-ip-filter中的域名使用fake-ip。
  • 黑名单模式下(blacklist),在fake-ip-filter中的域名使用redir-host。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
dns:
# ...
enhanced-mode: fake-ip
fake-ip-range: 198.18.0.1/16
fake-ip-filter:
- geosite:private
- '*.lan'
- localhost.ptlogin2.qq.com
- +.stun.*.*
- +.stun.*.*.*
- +.stun.*.*.*.*
- +.stun.*.*.*.*.*
- lens.l.google.com
- '*.n.n.srv.nintendo.net'
- +.stun.playstation.net
- xbox.*.*.microsoft.com
- '*.*.xboxlive.com'
- '*.msftncsi.com'
- '*.msftconnecttest.com'
- '*.mcdn.bilivideo.cn'
- WORKGROUP
fake-ip-filter-mode: blacklist
# ...

Clash DNS解析顺序

flowchart TB
  subgraph "Clash DNS"
    a("fake-ip")-->b("缓存")
    b-->c("nameserver-policy")
    c-->d("nameserver+fallback")
  end
  client("客户端")-->a

如图

  1. 如果启用了fake-ip,则根据fake-ip-filter判断是否需要使用fake-ip
  • 是,返回fake-ip给客户端,结束后续步骤
  • 否,继续下一步……
  1. 检查缓存中是否有当前域名的结果
  • 如果有就直接返回给客户端,结束后续步骤。
  • 如果没有记录或者已经过期(过期的记录先返回给客户端),继续下一步……
  1. 匹配nameserver-policy
  • 如果匹配到了当前的域名就按对应的DNS服务器解析,取得结果后返回给客户端并将结果写入缓存,结束后续步骤。
  • 如果未能匹配,继续下一步……
  1. 通过nameserverfallback两组并发解析,并通过fallback-filter过滤结果,取得结果后返回给客户端并将结果写入缓存,结束。

在连接页面中所有的连接目标都是IP,而不是域名

Clash通过DNS解析记录推测用户访问的网站。如果DNS配置有误,客户端的DNS请求绕过了Clash的DNS就会导致这个问题。可以通过开启域名嗅探解决。或者是尝试解决ClashDNS被绕过的问题(比如有其他的软件/插件开启了DNS劫持、重定向等功能)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
sniffer:
enable: true
force-dns-mapping: true
parse-pure-ip: true
override-destination: false
sniff:
HTTP:
ports: [80, 8080-8880]
override-destination: true
TLS:
ports: [443, 8443]
QUIC:
ports: [443, 8443]
force-domain:
- +.v2ex.com
skip-domain:
- Mijia Cloud
skip-src-address:
- 192.168.0.3/32
skip-dst-address:
- 192.168.0.3/32