最近又开始自行编译适合自己的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)
/https%3A%2F%2Frenyili.org%2Fpost%2Fopenwrt_dns_process%2FImage6.png)
概括来说,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请求结果。如下图:



那是不是把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端口去请求更加安全一些。

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,这个之后再研究吧。
Comments | NOTHING