项目地址: https://github.com/crzidea/doh
我知道大家很多人的分流规则是这样的:
- 国内域名转发到 DHCP 获取的 DNS
- 国外域名转发到 1.1.1.1
但是肯定会有漏网之鱼不在已知的域名列表里,该怎么办呢?我猜有能力的各位是这么配置的:
- 支持 EDNS Client Subnet 的环境中,比如在 dnsmasq 中配置,再将请求通过 DoH 转发到 8.8.8.8 。
- 不支持 EDNS Client Subnet 的环境中,比如 clash ,通过 fallback 配置根据默认的解析结果,如果不是大陆的 IP 再从 1.1.1.1 解析一遍。
但是上述方法都有一些小瑕疵:
- EDNS Client Subnet 虽然可以准确的解析出来离我们墙内最近的结果,但是当解析结果不在墙内时,有可能会产生相反的效果。比如 VPN 出口在美国,我们要访问的 CDN 虽然在国内没有节点,但是在日本有节点,这时我们的流量会路由到美国,再路由到日本,回程时也一样再绕回来。
- clash fallback 的方法目前已经不可靠了。我自己遇到过 Wikipedia 的 DNS 被污染后的解析结果是国内 IP 的结果。
在这个背景下,本着能不花钱就不花钱的原则,我开发了这个项目。用户解析 DNS 的时候,会同时向 Google DNS 查询两次:
- 第 1 个的 Client Subnet 参数带着本地 ISP 的 IP
- 第 2 个的 Client Subnet 参数带着 VPN 的 IP
如果第 1 个的解析结果对应的地区信息与我们想要的地区信息一致,就采纳第 1 次的解析结果,否则的话采用第 2 个。
这样做还会有以下好处:
- Github Actions 、Cloudflare Workers 、Cloudflare D1 全都是免费的,甚至 MaxMind 的最基础的数据库也是免费的。
- 不支持 EDNS Client Subnet 的客户端,比如 clash ,可以把查询参数放到 URL 参数中,也可以使用。
- 利用 Cloudflare 的网络资源和 Cloudflare 许诺的未来 D1 支持跨地区同步,理论上可以是分布式的。但是我没交钱,所以网络延时大概 200 ms 左右,有钱的大哥可以开个订阅试试。另外建议 D1 位置选择欧洲西部,别问我怎么知道的。
- GeoIP 数据库的更新过程是全自动的,自己完全不用管,不用担心长时间忘记更新数据库。感谢 Github Actions 和 MaxMind 。
- 甚至直接支持了 IPv6 和 HTTP/3 。
附带博客链接: https://crzidea.com/#/article/introducing-crzidea-doh