自开源EasyMosdns项目以来,很多用户已经在服务器上自建了无污染DNS,然而当DNS服务器并非在内网时,并不能获取最佳的解析速度。
这里讲解一下家用的分流策略,适合已经在使用无污染DNS的用户加速解析。
【DNS分流】
第一种是本地自建DNS,在IP分流的逻辑处理上,默认使用支持ECS的海外DNS分流,当返回国内IP时,使用国内DNS再次解析提升精准度,这就是EasyMosdns v2版本的设计思路;
第二种是本地只做国内域名规则的命中,其余域名分流交给有分流功能的无污染DNS处理,下面给出mosdns的配置文件:
# EasyMosdns Client v3.0 log: file: "./mosdns.log" level: error data_providers: - tag: chinalist file: ./rules/china_domain_list.txt auto_reload: true - tag: cdncn file: ./rules/cdn_domain_list.txt auto_reload: true plugins: # 乐观缓存的插件 - tag: cache type: cache args: size: 5000 compress_resp: true lazy_cache_ttl: 86400 cache_everything: true lazy_cache_reply_ttl: 3 # IP反查缓存的插件 - tag: reverse_lookup type: reverse_lookup args: size: 1000 ttl: 3600 handle_ptr: true # 调整TTL的插件 - tag: ttl_long type: ttl args: minimal_ttl: 600 maximum_ttl: 86400 # 转发AliDNS的插件 - tag: forward_alidns type: fast_forward args: upstream: - addr: "223.5.5.5" # 转发DNSPod的插件 - tag: forward_dnspod type: fast_forward args: upstream: - addr: "tls://1.12.12.12:853" enable_pipeline: true # 转发远程服务器的插件 - tag: forward_remote type: fast_forward args: upstream: - addr: "tls://8.8.4.4:853" enable_pipeline: true # 转发分流服务器的插件 - tag: forward_apad_pro type: fast_forward args: upstream: - addr: "https://doh.apad.pro/dns-query" bootstrap: "119.29.29.29" enable_http3: false # 匹配本地域名的插件 - tag: query_is_local_domain type: query_matcher args: domain: - "provider:chinalist" # 匹配CDN域名的插件 - tag: query_is_cdn_cn_domain type: query_matcher args: domain: - "provider:cdncn" # 主要的运行逻辑插件 - tag: main_sequence type: sequence args: exec: # 缓存 - reverse_lookup - cache # 本地域名与CDN域名处理 - if: "(query_is_local_domain) || (query_is_cdn_cn_domain)" exec: - primary: # 优先用AliDNS解析 - forward_alidns secondary: # 超时用DNSPod解析 - forward_dnspod fast_fallback: 50 always_standby: true - _return # 剩下的域名处理 - primary: # 优先用分流服务器解析 - forward_apad_pro secondary: # 超时用远程服务器解析 - forward_remote fast_fallback: 500 always_standby: false - ttl_long servers: - exec: main_sequence timeout: 5 # 监听地址配置 listeners: - protocol: udp addr: "0.0.0.0:53" - protocol: tcp addr: "0.0.0.0:53"
其中china_domain_list.txt、cdn_domain_list.txt两个规则文件可以在项目https://github.com/pmkol/easymosdns/tree/rules 中获取。
如果已经使用了smartdns、adguard home等DNS软件,可以将mosdns做为后端,以实现更多功能,当然也参考mosdns的分流思路使用这些软件直接分流。
【思路讲解】
对于绝大多数拥有分流功能的DNS程序而言:
核心逻辑一般会先判断国内域名,命中后使用国内公共DNS解析;
然后再去解析其余域名,根据解析IP的地理位置进行DNS分流,如果IP属于中国大陆则直接返回结果,反之则使用海外DNS再次解析后返回结果。
【思考一】
命中国内域名的处理很好理解,但当其余域名使用IP分流时,想获取一个域名的IP,首先要对这个域名进行解析,这时需要使用哪个DNS对域名进行第一次解析呢?
按照上述的DNS分流逻辑,很明显需要使用国内公共DNS完成首次解析,速度才是最快的,因为即使有DNS污染,解析出的污染结果并不包含中国大陆IP,所以只需要使用无污染的DNS重新查询这些结果,即可解决DNS污染问题。
事实上绝大部分DNS分流及代理工具的IP白名单分流也正是这样实现的。
【思考二】
以www.google.com的解析过程举例,首先请求国内公共DNS,获取到了一个污染结果75.126.115.192,这个结果不是中国大陆IP,所以需要去请求无污染DNS,最终获取到正确的解析结果。
那么问题来了,国内公共DNS记录了你对www.google.com的查询,也就是说国内运营商知道你访问了谷歌,而且查询两次DNS也降低了解析效率。
为了解决这个问题,代理域名黑名单出现了,命中黑名单的域名会直接使用无污染DNS查询,这也是代理工具比较常用的方法。
【思考三】
新的问题出现了,那就是黑名单的覆盖率,当进行DNS泄露测试时,会发现同时存在国内与海外的DNS,证明发生了DNS泄露,而且有些被污染的域名并不一定在黑名单中。
简单暴力的思路出现了,放弃IP分流,直接将非国内域名全部使用无污染DNS解析不就好了。
然而这仅在理论上可行,实际上部分域名的解析效果并不会很好,因为无污染DNS需要去请求海外公共DNS,即使是国内的无污染DNS也都是转发海外公共DNS实现的,延迟问题或许还可以在本地使用乐观缓存方案解决,可解析精准度问题呢?
在国内特殊的网络环境下,直接请求53端口的海外公共DNS是会被劫持污染的,所以一般是通过DoH或DoT来访问,抛开丢包、阻断这些可能遇到的问题不谈,即使可以直连使用,此时会发现解析结果全部到了海外地区。
对于一般的海外域名而言,这并不会影响什么,但对于有国内节点的域名,还不在国内规则列表中的域名,将会解析出一个海外的IP,导致访问速度变慢。
这时一些DNS支持ECS的作用就体现出来了,最常用的就是谷歌DNS,对于大多数域名而言,的确可以解决上述问题,然而并不是所有域名都可以使用ECS进行解析优化,最典型的就是使用Akamai厂商CDN服务的域名。
使用 nslookup www.microsoft.com 8.8.8.8 命令在国内主机上测试,会发现返回了香港IP,说明谷歌DNS的ECS功能并未对该域名生效,当换成国内公共DNS时,会发现返回了距离较近的国内IP,当然这里只是用微软官网的域名举例,实际上这个域名会被绝大多数国内域名规则收录,并不会出现访问速度变慢的问题,但这证明单纯使用海外支持ECS的公共DNS进行分流虽然可行但并不完全可靠。
额外提一下Cloudflare的Gateway服务,只需要拿几个国内拥有CDN的域名测试下精准度,以及感受下解析的延迟,就知道答案了。
如何更优雅的实现DNS分流,参考本文前面给出的两种DNS分流方案即可。