近日适逢某平方节日,Google国外网站陆续出现被墙的状况,想必大家都是知道的。

其实本人一直在使用SSH的Socket代理功能爬梯子,效果还是不错的,加上学校有原生IPv6支持,就算不走代理一般也能上各大网站。唯独有一点,不论是浏览器还是操作系统,DNS均使用了UDP协议,而UDP显然是无法走Socket代理的,所以对于Youtube、Facebook这些网站由于域名解析问题,仍旧无法访问。

不过,事情总有解决的办法。

由于习惯于使用UDP协议的DNS,很多人不知道其实DNS也是支持TCP协议的,功夫网只对UDP的DNS进行了劫持和污染,TCP DNS则可畅通无阻。

唯一的问题就是,浏览器、操作系统等都无法直接使用TCP DNS,我前一段时间一直在使用Tcp-DNS-proxy解决这个问题。这是一个基于Python的小程序,可以通过TCP连接DNS服务器,并在本地监听UDP53端口,实现TCP DNS的中转,程序简单运行方便,比较推荐。

不过Tcp-DNS-proxy本身也存在着一些问题,比如没有完整的缓存机制,导致查询速度较慢,程序稳定性和抗并发性一般。于是我考虑能否有更加稳定的解决方案?

最终还是选定了BIND这一老牌的DNS服务器,利用forward功能可以比较容易的实现对DNS的转发。Ubuntu 14.04下修改配置如下:

/etc/bind/named.conf.options
...
options {
directory "/var/cache/bind";
// If there is a firewall between you and nameservers you want
// to talk to, you may need to fix the firewall to allow multiple
// ports to talk. See http://www.kb.cert.org/vuls/id/800113
// If your ISP provided one or more IP addresses for stable
// nameservers, you probably want to use them as forwarders.
// Uncomment the following block, and insert the addresses replacing
// the all-0's placeholder.
forward only;
forwarders {
8.8.8.8;
8.8.4.4;
};
allow-query {
any;
};
//========================================================================
// If BIND logs error messages about the root key being expired,
// you will need to update your keys. See https://www.isc.org/bind-keys
//========================================================================
dnssec-validation auto;
auth-nxdomain no; # conform to RFC1035
listen-on-v6 { any; };
};
...

仅仅这样是不够的,我们需要的是TCP DNS转发(代理),但经过测试BIND会首选UDP解析进行递归查询,经过搜索Google、查看官方文档、查看源代码,我发现从配置上修改这条路是行不通的。

没有办法,只能动手改源代码了。不过还好,最近嵌入式课程实验我尝试把NginX移植到了ARM平台上,对于裁剪代码还是有心理准备的。

经过几个小时的努力,翻看了几个重要的.c文件,最终我确定了BIND9(这里选用bind-9.10.0-P1)发出查询的函数,是位于lib/dns/resolver.c文件第1403行的fctx_query函数,节选其中1446至1451行如下:

  1.     query->mctx = fctx->mctx;
  2.     query->options = options;
  3.     query->attributes = 0;
  4.     query->sends = 0;
  5.     query->connects = 0;
  6.     query->dscp = addrinfo->dscp;

其中query->options = options;这一行中options利用位运算存储了是否使用TCP连接的变量DNS_FETCHOPT_TCP,我们需要做的就是将这一行改为:

  1. query->options = options | DNS_FETCHOPT_TCP;

强制让BIND使用TCP进行递归查询。之后进行编译,覆盖二进制文件即可,在此就不再赘述。效果如下:

可以看到,第1、36报文是客户端查询BIND服务器,为UDP协议;其他报文为BIND查询8.8.8.8,为TCP报文(颜色不同)。

最新文章

  1. UV动画
  2. js-sort数组排序
  3. CCNA网络基础(一)
  4. UI学习之常用方法
  5. caffe学习系列(7):Blob,layer,Net介绍
  6. 第一章 Mysql 简介及安装和配置
  7. Python模拟登录实战(一)
  8. 利用merge存储引擎来实现分表
  9. web项目错误页面友好处理404,500等
  10. macbook配置xdebug+vscode
  11. 解析/proc/net/dev
  12. 学习REST
  13. shell sort result to self
  14. 爬虫--反爬--css反爬---大众点评爬虫
  15. idea 断点上面有x
  16. Kafka集群扩展以及重新分布分区
  17. 子串字谜substring anagrams
  18. Sensitivity, specificity, and reproducibility of RNA-Seq differential expression calls RNA-Seq差异表达调用的灵敏度 特异性 重复性
  19. 2019.3.5 控制台输出log4j得有些报错信息
  20. 【BZOJ2339】卡农(递推,容斥)

热门文章

  1. 初步认知java的方法
  2. C#对象比较
  3. java的三大框架(三)---Hibernate
  4. 通过源码成功启动odoo 10.0
  5. uva 10820
  6. BLOCK封装带菊花的网络请求
  7. C++ operator 的一种不会的用法
  8. 详细解说Java Spring的JavaConfig注解 【抄】
  9. photoshop,黑白转彩色单色
  10. CodeIgniter 开发,支付宝接口调用实例