一、背景

  1. adg 监听 53 端口,用于提供日志查询和设备管理,mosdns 为唯一上游
  2. mosdns 负责 DNS 分流,国内域名走国内 DNS,国外走 OpenClash DNS
  3. OpenClash fake-ip 模式,GeoIP 规则 no-resolve,MATCH 走代理
  4. 通过 adg 查询 ipleak 的全部 DNS 请求,响应的全都是 fake-ip
  5. 通过 ipleak 检查 DNS 泄漏,发现列表中出现了大量中国 DNS 服务器响应

dns-leaking-check-ipleak-china.png

二、排查

关于泄露点的几个猜想:

  1. mosdns 分流结果并不是国外,而是分流失败,走了 fallback 策略,而 fallback 同时请求国内和 OC DNS 服务器,结果国内服务器返回污染地址,于是才采用了 OC 的 fake-ip 返回给 adg,于是看上去仿佛是正确分流为国外流量了?
  2. mosdns 分流正确,但 OC 在返回 fake-ip 的同时还是向上游服务器发了请求?
  3. 浏览器/操作系统向 DHCP 下发的 DNS 发起请求的同时,悄悄擅自向其他服务器也发了请求?(不太可能)

对于猜想一,去 mosdns 设置中开启了「防止 DNS 泄漏」,该设置项备注内容为:“启用此选项 fallback 策略会强制转发到远程 DNS”。随后再查看 ipleak 情况,发现确实没有再出现泄漏了。(猜想二和三就可以排除了)

dns-leaking-check-ipleak.png

三、分析

由此可以实锤:

  1. mosdns 在处理 ipleak 的分流时,一定触发了 fallback
  2. mosdns 的 fallback 策略中一定配置了国内 DNS
  3. OC fake-ip 模式在 DNS 阶段只是单纯返回 fake-ip
  4. 浏览器/操作系统没有进行多余的 DNS

四、验证

找到 mosdns 的内置配置文件(/etc/mosdns/config.yaml),定位到 fallback 逻辑。可以看到 primary 为 query_is_non_local_ip,secondary 才是转发至远程 DNS(OpenClash)。

dns-leaking-check-1.png

继续定位到 query_is_non_local_ip,发现其处理逻辑是,首先请求国内 DNS 服务器,若国内 DNS 服务器响应的查询结果为国外 IP 则丢弃响应。

dns-leaking-check-2.png

当在 mosdns 设置页面把「防止 DNS 泄漏」的开关打开后,配置文件中的 primary 和 secondary 都变成了 forward_remote_upstream,于是乎自然就消除泄漏了。

dns-leaking-check-3.png

五、结论

由此可以确定原始问题就是 mosdns 在 fallback 的时候查了国内服务器导致的 DNS 泄漏… 而为什么 ipleak 域名会不在 geosite_geolocation-!cn 之列呢??

猜想这或许是 geosite 维护者有意为之,用于为测试者暴露出 fallback 情况下的泄漏问题的?不过事实上绝大部分的主流网站,或者说 GFW 黑名单上的网站肯定都是在统计之列的,漏网之鱼往往是国内小站和国外小站,所以说这到底这算不算 DNS 泄漏呢?感觉就是一个仁者见仁智者见智的问题了。毕竟「DNS 泄漏」这个概念本就只有在科学的时候才有意义,如果你认为只要访问诸如谷歌、油管之类的重点大站时没有泄漏就没有问题的话,那这个问题确实是可以忽略。

如果就算是小站你也不接受泄漏,那么就为 mosdns 的 fallback 禁用本地查询吧,唯一的副作用就是少数国内站点 fallback 时也会走代理,需要手动维护一下 mosdns 的白名单。