Pages

Saturday, 28 October 2017

庖丁解牛 - DNS


fqrouter为了解决可访问性问题,接入到自由的网络要解决的第一个问题就是DNS。DNS不仅仅是查询一个域名能够拿到IP那么简单,光DNS就可以分解为如下的子问题:
  • DNS的配置
  • 域名解析的正确性
  • 联通电信的线路优化
  • Host文件的管理
DNS的配置
如果我们以前使用的是socks5(ssh)代理,根本不会有DNS劫持的问题,因为域名是由远端的sock5代理服务器解析的。如果我们以前使用的是VPN代理,而且DNS服务器是国外的,那么DNS解析也不会是问题,VPN代理会保护我们的DNS解析操作。DNS问题只有在翻墙与访问的设备不在一台机器上时才会是问题。如果是socks5代理,要求用户配置浏览器,让浏览器利用socks5代理服务器解析域名。如果是VPN代理,要求用户配置DNS服务器的IP到国外的服务器。fqrouter做为一个路由器设备,显然不希望用户重新手工配置每一个接入了fqrouter网络的设备。所以,这里解决的主要是一个是否需要手工配置的问题。
fqrouter对于配置问题的解决办法是暴力的。对于手机自身的网络流量,使用一条iptables规则解决问题:
iptables -t nat -I OUTPUT -p udp ! -s 10.1.2.3 --dport 53 -j DNAT --to-destination 10.1.2.3:5353
对于加入fqrouter网络的设备产生的DNS查询,使用另外一条iptables规则:
iptables -t nat -I PREROUTING -p udp ! -s 10.1.2.3 --dport 53 -j DNAT --to-destination 10.1.2.3:5353
这两台规则劫持了所有目标端口号是DNS端口号(53)的UDP连接。虽然浏览器仍然认为它连接的是系统配置的DNS服务器(比如8.8.8.8),但其实真正连接到的是10.1.2.3:5353这个端口的DNS服务器。
这种iptables的暴力做法显而易见的好处是完全不需要在设备或者浏览器上做任何配置。只要DNS查询经过了fqrouter所在的机器,就会被劫持到fqrouter提供的DNS服务器上。
上面的iptables规则中有一个诡异的地方时排除了所有来源地址是10.1.2.3的连接。这是因为把流量倒给了fqdns之后,fqdns自己还是需要去查询上级DNS的。而这些查询为了避免被这两条iptables规则再次劫持,就必须绑定到10.1.2.3这个源IP做查询,然后在iptables规则里排除掉这些查询。否则就死循环了。这种排除法除了可以用排除源IP的方法,还可以使用–mark或者–owner利用mark或者进程的用户/组的ID做排除。不过在Android手机是不能保证所有的手机都支持–mark和–owner,只有比较新的手机才支持。
域名解析的正确性
直接使用国外的DNS服务器,是不能解析出很多了域名的正确结果的。原因是GFW抢答了错误答案。解决办法是记录一个GFW抢答的错误答案的黑名单,如果发现答案是黑名单中的,则丢弃等待DNS服务器回答的正确答案。有的时候,GFW会对DNS查询丢包,这样无论等待多久也不会收到DNS服务器回答的正确答案了。这个时候需要切换到TCP协议,查询DNS服务器。虽然GFW可以对DNS over TCP做关键字检查,但是目前还没有大规模使用。所以在目前的形势下,用黑名单结合DNS over TCP就可以比较完美的解决域名解析的正确性问题。
这部分的代码实现是由fqdns子项目提供的。前面通过iptables重定向到的DNS服务器,就是fqdns。fqdns自身是一个DNS服务器,所有的DNS查询先由fqdns接收,然后再由fqdns查询上一级的DNS服务器。
使用–strategy pick-right参数启动fqdns就实现了GFW的错误答案黑名单。
使用–fallback-timeout 3参数启动fqdns就实现了超时之后切换到DNS over TCP。
联通电信的线路优化
因为国内有很多网站都是有联通和电信两种线路的。当用户以联通的IP去做域名解析的时候,得到的是联通线路的服务器地址。当用户以电信的IP去做域名解析的时候,得到的就是电信线路的服务器地址。如果联通的用户拿到的是电信的服务器地址,访问速度就会变得慢很多。如果我们用8.8.8.8做域名解析,8.8.8.8再去向权威服务器查询域名,那么8.8.8.8就是权威DNS服务器认为的客户端。如果它认为8.8.8.8是电信线路更优的话,即便是联通的用户,也会被分配到电信的服务器地址。
这个问题没有一个特别好的办法。我们不能使用联通、电信分配给你的DNS服务器。因为用这些国内的DNS服务器,是无论如何无法保证域名解析的正确性的。我们也不能总是依赖8.8.8.8这些国外的服务器,因为它不能保证线路的最优。fqdns的实现办法是内置一个国内比较大的网站的域名列表。对于这些域名的解析,使用114dns来做DNS查询。至于是否选择了告诉的线路,这就要靠114dns来保证了。
使用–enable-china-domain –china-upstream 114.114.114.114参数启动fqdns实现了对国内域名解析的线路优化。
Host文件的管理
Host文件可以对某些域名指定IP。这种方式对于google这样的网站来说特别重要。一方面google的ip众多,只要指定的IP没有被GFW关照,就可以获得非常好的使用体验。另外一方面,Google自身封了很多的代理服务器,因为Google不欢迎别人通过代理服务器来爬它的查询结果。而且Google的很多HTTPS服务处于半残废的状态,GFW会以时间为周期完全丢包,造成其服务不稳定的状况。这种丢包是针对特定IP的,只要选择的Google IP没有被关照,就不会出现这样的不稳定状况。
但是Host文件的缺点是需要手工更新。fqrouter显然不希望每次要更新Google的IP都让用户升级一个新的版本。解决办法就是对于指定的域名,比如说google.com,改成google.com.fqrouter.com来解析。这样fqrouter就可以控制google.com解析的结果了,相当于在云端保存了一份公共的Host文件。
使用–enable-hosted-domain –hosted-at fqrouter.com启动fqdns就可以达到关照特殊域名的目的。哪些域名被特殊处理是内置的,基本上都是google的域名.
from http://fqrouter.tumblr.com/post/51783097591/庖丁解牛-dns
----------

https://github.com/fqrouter/fqdns,这个项目用不了,放弃。
-------

相关帖子:
http://briteming.blogspot.com/2013/05/fqsocks.html

No comments:

Post a Comment