使用smartdns和docker搭建私有防劫持dns服务
引言
最近在家使用移动宽带,使用的ISP DNS出现了DNS的污染,经常会将域名错误解析来劫持域名,十分烦恼。由于DNS本身使用的UDP协议是先到先得,也就是先应答的报文会被视为有效报文。研究了一下ISP的DNS抢答部署,发现是在光猫一级。最开始是希望使用chromium的DNS over https功能,但是还有个问题是其他的设备或者软件使用时,还是会被劫持。因此研究了一下,在windows上搭建一个私有的DNS服务。
我的需求大概是以下几点:
能够使用DNS over TLS/DNS over https作为上游
这点非常重要,因为DNS抢答发生在光猫一级的时候,如果还使用UDP协议作为上游,也就意味着这一层私有DNS向上拿到的仍然是被劫持的结果。
方便部署
这一点主要是为了方便迁移平台,因为我的目的是让所有使用的设备都能使用这个服务。而不需要对于不同平台弄不同的解决方案。
综合上面两点主要的需求,我找了几个比较热门的解决方案.其中最多人在用的应该是dnsmasq+dnscrypt。这种方案的好处显而易见,就是用户群体大,维护方便,相对来说不需要自己太多折腾。但是缺点是dnscrypt不支持指定ISPDNS,这样会使得CDN失效。这样对于访问速度而言伤害比较大。对此,幸运的找到了smartdns项目。它最符合我需求的一点就是
- 多DNS上游服务器
支持配置多个上游DNS服务器,并同时进行查询,即使其中有DNS服务器异常,也不会影响查询。- 返回最快IP地址
支持从域名所属IP地址列表中查找到访问速度最快的IP地址,并返回给客户端,提高网络访问速度。- 支持多种查询协议
支持UDP,TCP,TLS, HTTPS查询,以及非53端口查询。
其他特性参见https://github.com/pymumu/smartdns
搭建过程
smartdns本身支持了很多部署方式例如deb包、ipk包路由器固件等等。在官方的部署方式中亦给出了WSL子系统的部署方式。并且给出了脚本来进行部署。但是我在尝试了WSL的子系统方式部署后,发现一个问题是,WSL由于隐藏了比较多的细节,或者说实现的比较复杂,出现问题之后比较难debug。因为之前本机部署redis服务的时候,在Windows下搭建了一个docker。因此就试着
1 | docker search smartdns |
然后就发现了ghostry/smartdns这个镜像。因为这个作者本身也是smartdns的使用者,于是将其打包成了镜像,并且上传到docker hub。
对于smartdns的docker搭建,因为有了这个镜像简单了很多,只需要:
1 | //拉取镜像 |
在上述命令运行成功之后,ghostry的docker镜像中原来就已经配置好了一份,但是没有包含被污染的ip列表,以及使用的上游DNS等等。这里上一份我自行修改之后的配置文件
1 | conf-file blacklist-ip.conf |
其中blacklist-ip.conf文件我使用的是这一份blacklist-ip.conf,配置的参数含义参见https://github.com/pymumu/smartdns
在完成以上的配置步骤之后,就可以尝试将DNS改为127.0.0.1进行测试啦。
关于ISPDNS,记得对nameserver进行配置
参照
- https://github.com/pymumu/smartdns
- https://blog.ghostry.cn/server/894.html
- https://abbypan.github.io/2017/10/11/dnsmasq-dnscrypt-dnswrapper
我的使用配置文件在 <../assets/blacklist-ip.conf> <../assets/gfw.conf> <../assets/config.conf> 需要的话可以自取