自开源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分流方案即可。