自编译OpenWrt,解决DNS污染、不可描述的那些事


最近又开始自行编译适合自己的OpenWrt系统,用在软路由、各种LXC环境,以及一堆7621A的设备上(7621A用OpenWrt开启硬件NAT后真是神器)。折腾OpenWrt当然是为了获得一个干净而自由的网络环境,所谓与操蛋的GFW斗,其乐无穷也。

使用的源代码是lean的源代码,再加上Server酱等应用包。既然使用lean的源代码,出国留学当然就是SSR+了。SSR+针对GFW列表中的域名,会使用PDNSD TCP通过VPS去解析DNS,这保证了GFW列表中的域名获得的IP是没有被GFW污染,并且离VPS更近的。但是在使用的时候发现部分国外网站依然会出现DNS被污染的情况。

于是研究了一下SSR+对DNS解析的分流原理,这里有一篇不错的文章: Lean OpenWrt DNS解析流程研究 - 任意的Blog (renyili.org)

概括来说,SSR+是利用GFW列表来判断一个域名是否需要使用VPS进行解析(即使用大陆白名单模式也是这样,因为域名在解析之前,是无法知道该域名对应的服务器在国内还是国外的。除非使用accelerated-domains.china.conf这种列出了所有中国域名的列表,可以参考这个方案: 加入 SmartDNS 其实主要是用来恶心那些 Up 主 和 小白们的 · Issue #2551 · coolsnowwolf/lede (github.com)https://blog.stdio.io/693,但是这种列表始终会有漏网之鱼 ),所以如果一个国外网站的域名不在GFW列表之内,那么就会使用dnsmasq默认的DNS服务器去解析,就很容易被GFW污染。

GFW的DNS污染骚操作,目前主要是当我们通过UDP协议和53端口去请求DNS服务器时,在背后猥琐的对DNS解析结果进行偷梁换柱(通常是随机替换成国外的facebook、twitter等网站的IP),就算是使用8.8.8.8也不例外。我们可以在OpenWrt安装bind-dig软件包,用dig命令去查看各种情况的DNS请求结果。如下图:

通过8.8.8.8查询u2.dmhy.org,返回了被污染的DNS查询结果
通过TCP去查询,就会返回正确的结果
通过5353端口去请求OpenDNS的服务器,也可以返回正确的结果

那是不是把dnsmasq的DNS转发一项设置为208.67.222.222#5353就可以了呢。这样确实是解决了DNS污染,但是这样的话解析国内的域名速度会比较慢,而且解析的结果可能也不是你访问较快的服务器(所谓的CDN友好)。

我们的目的是既要国内网站查询DNS速度和访问速度快,又要国外的网站查询到的DNS是干净未被污染的(即使是本地请求而不是通过VPS请求),那么使用ChinaDNS进行分流就是一种很不错的方案(也可以选择前面说的accelerated-domains.china.conf方案 )。

这里有一篇文章分析了ChinaDNS的原理,非常巧妙: ChinaDNS原理与源码分析 | Cyberloginit

简单来说,ChinaDNS会同时向国内和国外的可信DNS服务器进行请求,然后等国内的DNS服务器返回IP结果(通常情况下国内DNS会更快返回结果),通过中国IP段列表判断返回的IP是否是国内的IP,如果是国内IP,则直接使用这个IP;如果是国外IP,则认为不可信,继续等待国外可信DNS服务器的返回结果。

这样既不会影响国内域名的解析速度,在解析国外域名时也可以得到正确的解析结果,妙啊。

ChinaDNS可以直接在github下载编译好的ipk文件安装,也可以在编译的时候编译到固件里。ipk下载地址:
https://github.com/aa65535/openwrt-chinadns
https://github.com/aa65535/openwrt-dist-luci

安装完之后如此设置:

这里监听了5353端口,上游服务器设置了一个国内的114.114.114.114,另外一个127.0.0.1#5053是我在OpenWrt上用DNS HTTPS Proxy搭建的doh域名解析服务,作为国外可信DNS服务器。也可以直接用208.67.222.222#5353或者208.67.222.222:443,但是感觉用doh请求DNS会比用UDP协议5353端口去请求更加安全一些。

DNS HTTPS Proxy监听5053端口,作为ChinaDNS上游服务器的国外可信DNS服务器

dnsmasq中的DNS转发设置为ChinaDNS的127.0.0.1#5353:

Turbo ACC中的DNS加速可以关掉。这时在路由器运行dig u2.dmhy.org @127.0.0.1或者dig u2.dmhy.org @127.0.0.1 -p 5353,就都可以获得正确的结果了,网络又干净又快速!爽啊

去尼玛的污染吧!

最后再搞个定时任务脚本,定时更新中国IP段列表文件:

脚本内容(别忘了给执行权限):

#!/bin/sh

wget -O- 'http://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-latest' | awk -F\| '/CN\|ipv4/ { printf("%s/%d\n", $4, 32-log($5)/log(2)) }' > /etc/chinadns_chnroute.txt

搞定!ChinaDNS缺点是不支持ipv6域名解析,而ChinaDNS-NG则支持,另外PassWall也可以使用内置的ChinaDNS-NG进行域名解析的分流,我也在自己编译的OpenWrt中集成了PassWall,这个之后再研究吧。

声明:爱玩咖 – 生命在于折腾|版权所有,违者必究|如未注明,均为原创|本网站采用BY-NC-SA协议进行授权

转载:转载请注明原文链接 - 自编译OpenWrt,解决DNS污染、不可描述的那些事


Carpe Diem and Do what I like