smartdns返回结果仍存在污染问题一例

之前我写过关于使用smartdns将china和其他地区分流的案例,在正常使用很长时间后,最近出现了查询结果混入被污染的IP的问题。

问题描述

DNS系统架构为:一台adguardhome服务器,上游为smartdns,adg提供去广告、访问控制和日志查询功能,方便排错,smartdns负责分流。

问题是最近出现了被污染的结果,从adg控制台上可以看到是返回了属于fackbook的随机IP及常见的几个污染黑名单IP,但不经常发生,一小时出现数次,也可能出现一段时间后消失。

检查了一下smartdns的配置,其查询流程严格按照如下:

客户端发起查询后,如果符合 -group china的规则,则发给 223.5.5.5 处理,-group china 规则为felixonmars的DNSMASQ CHINA LIST (项目地址)。-group china 设置了 –exclude-default-group 以确保来自洼地的结果不会污染外溢。

此外我设置了两个私有的DOH服务器(DOH1、DOH2),除了 -group china 外的其他域名全部发给这两个服务器处理。

server 223.5.5.5 -group china -exclude-default-group
server-https https://doh1.myserver.com/dnsquery
server-https https://doh2.myserver.com/dnsquery

我想可能是某种原因导致DOH查询失败后,以某种形式回落到普通服务器上,进而返回了污染的结果。

将adg中缓存时间降低,以便让其多次尝试解析。实验证明降低了缓存时间后,情况有所好转,出现被污染IP的概率极大下降了,但仍然有小概率出现。

问题原因

去smartdns的github上查询有关默认组(default group)的内容,没有查到smartdns在默认组查询失败后的行为逻辑,但在github论坛上看到这样一条issue

显然github上的分析都是错的,但是他提到了 server 223.5.5.5 – group bootstrap

因为我的DOH服务器本身也需要解析域名(doh1.myserver.com),所以需要设置一个bootstrap DNS 服务器来解析DOH服务器自己的域名:

server 223.6.6.6 -group bootstrap

我的doh1.myserver.com会单独从223.6.6.6解析。如果发生一个需要从DOH1服务器上解析的请求example.com,应该是先从223.6.6.6解析到doh1.myserver.com 的IP,再建立到DOH1的https链接,解析example.com。

那么如果在DOH1、DOH2都因为某些原因查询失败的情况下,由于bootstrap组没有-exclude-default-group,在bootstrap组中的223.6.6.6也会被用来直接查询 example.com,污染结果就是从223.6.6.6来源的。

也就是说,对于:

server 223.6.6.6 -group bootstrap
server 223.6.6.6 -group bootstrap -exclude-default-group

smartdns的行为是不同的。在没有 -exclude-default-group时,对doh1.myserver.com的查询一定会从-group bootstrap组里的服务器查询,因为命中了server 223.6.6.6 -group bootstrap

但对于不在group china组,也不在group bootstrap组里的域名的查询,有可能会使用bootstrap 组的服务器查询。因为-group bootstrap 是让在bootstrap组里的域名一定使用这个组的服务器,但也未禁止其他域名使用这个组的服务器。要禁止其他的域名使用这组服务器,必须加上-exclude-default-group

而这个问题以前之所以不明显,是因为最近因为显而易见的原因,DOH服务器可能受到了某种干扰(显然),导致短时间内DOH1和2同时查询不成功,smartdns自动选择了唯一一个可用的服务器(当然只有bootstrap了),污染就这么出现了。

解决方案和提升

解决方案当然很简单,要么禁止其他请求使用bootstrap 组 -exclude-default-group ,要么直接把DOH1和DOH2的IP写死在host里,后者更简单,因为自己的DOH服务器嘛IP肯定不会变,而且还省出了查询时间,速度更快了。

但是,如果DOH1和DOH2同时查询失败,岂不是会直接返回错误?

再回到整个DNS体系里来思考:

后面还有一个adg呢,主要是提供访问控制(如去广告),日志(安全目的)和方便的控制台,其只有唯一的一个上游,上游是smartdns。那可以认为adg实际上就是smartdns的缓存服务器。那smartdns本身就没有缓存的必要了,smartdns的工作主要应该是分流、防污染,其他任务交给adg。

那再进一步思考,smartdns的测速功能也没有意义了。因为不在china的IP,本身也要过代理,测速要么是无代理直连的速度,要么根本不通(IP都墙了你还测个屁呀)。而且测速会造成潜在的安全问题(频繁发出大量ICMP请求,对于特殊国家来说总是潜在隐患),那么关闭测速。

进而,smartdns的缓存也意义不大,cache 可以减少到 512-1024(按实际情况)。既然cache小了,TTL也没必要大,把TTL也减小为1-2分钟(最小TTL1分钟,最大2分钟)。

如果DOH服务器查询失败,只要不是DOH服务器被墙,则过几分钟再查也行,这几分钟里还有adg缓存呢,于是关闭提供过期缓存的功能、关闭持久化缓存。

向下游adg提供的结果TTL1分钟。

增加一组私有DOH服务器提升稳定性(没有也可以用公共的,不过估计都被墙完了)

cache-size 512
cache-persist no
prefetch-domain yes
serve-expired no
serve-expired-ttl 3600
speed-check-mode none
rr-ttl-min 60
rr-ttl-max 120
rr-ttl-reply-max 60
log-level warn
server 223.6.6.6 -group bootstrap -exclude-default-group
#这里也可以直接写死IP
server 223.5.5.5 -group china -exclude-default-group
server 114.114.114.114 -group china -exclude-default-group
server-https https://doh1.myserver.com/dnsquery
server-https https://doh2.myserver.com/dnsquery
server-https https://doh3.myserver.com/dnsquery

而缓存的任务则交给adg:

缓存大小1024000为最多缓存2000个结果(每个DNS结果为512字节),如果最多缓存1000个就是512000。

最小TTL 1分钟,最大2分钟(保持和smartdns一致)

乐观缓存为开启过期缓存,假设smartdns查询失败,还能从过期缓存中提取结果。(而smartdns就要关闭过期缓存,以便重复查询)。

发表回复

您的电子邮箱地址不会被公开。