如何避免 Brook 的 虚拟 DNS 不生效

https://www.txthinking.com/talks/
Updated at: 2023-05-13
cloud@txthinking.com

x

虚拟 DNS 的目的是什么

Brook 通过虚拟 DNS 来拿到域名,进而去做一些基于域名的任务,比如用 hosts 指定 IP 等。

虚拟 DNS 的 TTL 是 60 秒,Brook 断开再重新连接会重置虚拟 DNS 数据,但是一些不遵守标准的 App 可能自己缓存超过 60 秒很久才重新查询 DNS,这样 Brook 重新连接重置虚拟 DNS 后 App 仍然尝试连接之前的虚拟 IP 就会失败,点名批评 Instagram,可以用脚本让指定域名不走虚拟 DNS。

虚拟 DNS 是如何工作的

  1. Brook 客户端首先会配置系统 DNS
  2. 当其他应用进行域名查询时,会向系统 DNS 的 53 端口通过 UDP 协议进行查询
  3. Brook 会拦截 UDP 53 端口的数据,并向查询者返回一个虚拟 IP
  4. 查询者拿到虚拟 IP 后,会继续连接此 IP
  5. Brook 此时拿到要连接的 IP 后,如果发现是虚拟 IP,则会将 IP 转换为域名。因为 Brook 在内存里保存了一个虚拟 IP 和域名映射的字典
  6. 然后 Brook 将域名地址传递到服务端,让服务端来进行连接

可以看得出来,本地全程都不知道真正要连接的 IP 地址。

以上只是用最简单的流程来方便理解虚拟 DNS 是如何工作的,实际流程还有规则脚本等很多其他环节。

如何避免虚拟 DNS 不生效

上面我们知道了虚拟 DNS 是通过拦截系统 UDP 53 端口来工作的,所以我们要避免应用或系统走其他方式查询域名。

关闭系统安全 DNS

Android

Settings -> Network & internet -> Private DNS -> Off

Windows

Settings -> Network & Internet -> Your Network -> DNS settings -> Edit -> Preferred DNS -> Unencrypted only -> 8.8.8.8

iOS

继续往下看

macOS

继续往下看

关闭浏览器安全 DNS

Chrome 手机版

Settings -> Privacy and security -> Use secure DNS -> Off

Chrome 电脑版

Settings -> Privacy and security -> Security -> Use secure DNS -> Off

避免从普通 DNS 升级到安全 DNS

也就是说,明明你的系统 DNS 配置的普通 DNS,但是最后查询却走的是安全 DNS。

这是因为,系统或浏览器会向系统 DNS 发起一个查询,来询问是否支持 DOH,如果支持后续就会升级使用 DOH 来查询。比如 8.8.8.8

brook dnsclient --dns 8.8.8.8:53 -d _dns.resolver.arpa -t SVCB
;; opcode: QUERY, status: NOERROR, id: 52504
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 4

;; QUESTION SECTION:
;_dns.resolver.arpa.    IN       SVCB

;; ANSWER SECTION:
_dns.resolver.arpa.     86400   IN      SVCB    1 dns.google. alpn="dot"
_dns.resolver.arpa.     86400   IN      SVCB    2 dns.google. alpn="h2,h3" dohpath="/dns-query{?dns}"

;; ADDITIONAL SECTION:
dns.google.     86400   IN      A       8.8.8.8
dns.google.     86400   IN      A       8.8.4.4
dns.google.     86400   IN      AAAA    2001:4860:4860::8888
dns.google.     86400   IN      AAAA    2001:4860:4860::8844

可以看见,8.8.8.8 支持 DOT 和 DOH。

不过放心,如果开启了虚拟 DNS, Brook 客户端会帮你阻止了这个 SVCB 查询

避免系统或浏览器直接查询安全 DNS

也就是说,明明你的系统 DNS 配置的普通 DNS,即使没有升级查询,但是最后查询却走的是安全 DNS。

这里因为系统和浏览器内置了一些主流安全 DNS 的信息,比如如果发现是 8.8.8.8,知道这个 DNS 也支持 DOH,就不会再问,而是直接使用 DOH。这时我们可以用脚本阻断这些连接

text := import("text")
f := func() {
    if in_dnsquery {
        if in_dnsquery.domain == "dns.google" {
            return { "block": true }
        }
        return
    }
    if in_address {
        m := in_address
        if m.ipaddress && (m.ipaddress == "8.8.8.8:853" || m.ipaddress == "8.8.8.8:443" || m.ipaddress == "8.8.4.4:853" || m.ipaddress == "8.8.4.4:443" || m.ipaddress == "[2001:4860:4860::8888]:853" || m.ipaddress == "[2001:4860:4860::8888]:443" || m.ipaddress == "[2001:4860:4860::8844]:853" || m.ipaddress == "[2001:4860:4860::8844]:443") {
            return { "block": true }
        }
        if m.domainaddress && text.has_prefix(m.domainaddress, "dns.google:") {
            return { "block": true }
        }
        return
    }
}
out := f()

这里有例子

配置一个不支持 DOH 的系统 DNS

当然你也可以配置一个不支持 DOH 的系统 DNS,比如用 brook 自建一个 DNS

brook dnsserver --listen :53

配置一个不存在的系统 DNS 也行

你可能会说,上文全程都没有真正向这个系统 DNS 发起真实网络连接,填一个不存在的 DNS 也行。

针对 A/AAAA 的确如此,但是如果是 MX 或其他类型就会向这个系统 DNS 发起真实网络连接,所以还是要填写一个真实存在的 DNS。


评论