Openwrt架设DNS转发器,解决污染问题

鉴于境外技术网站经常有河蟹出没,所以有必要折腾一下。

 

关于DNS劫持和DNS污染的概念和区别,就不多说了。网上都有很多解释。解决方案无非就几种。

 

1.使用非53的udp端口。这个方法显然不具备实操意义,好少有开放非53UDP端口的dns服务器。

2.使用TCP 53端口查询,其中google的8.8.8.8就支持

3.使用加密的DNS协议,opendns貌似提供了解决方案。

 

查了一下openwrt有提供unbound这个软件包,可以非常方便地部署到路由器上。

unbound支持使用TCP协议进行DNS查询,所以只需要把DNS请求用TCP协议转发出去境外的DNS,就可以解决污染问题了。

虽然DNS的协议规定TCP协议也是其可以使用的协议,一般软件发出都是UDP 53端口来,所以需要做一个UDP转TCP的DNS转发器。

利用Openwrt里面自带了dnsmasq就能实现了。以下是实现方法。

 

先下载unbound。

opkg update
opkg install unbound


需要注意的是,如果使用Dreambox,他提供的unbound版本过低,不能提供TCP转发功能。我已提交了patch给Dreambox项目了,不过貌似项目管理者太繁忙没有处理这个任务单....

https://dev.openwrt.org.cn/ticket/84#

如果在Dreambox强行安装trunk或者Attitude Adjustment提供的unbound,会有lib依赖的问题,无法正常使用。

所以要么就不要用Dreambox,要么就按照我那个任务单里面说的方法把新版的unbound移植过来并编译Dreambox,十分折腾,呵呵。

 

由于dsmasq使用了udp53端口,所以unbound要换成另一个端口,我这里改成5353,然后打开tcp-upstream选项,意思是使用TCP协议转发请求至上游DNS。

安装完成之后,编辑unbound的配置文件/etc/unbound/unbound.conf,加入或找到相应的行去掉注释。

port: 5353
tcp-upstream: yes
forward-zone:                                                               
        name: "."                                                           
        forward-addr: 8.8.8.8                                                 
        forward-first: no  

 

把unbound设置成开机启动,然后启动unbound

/etc/init.d/unbound enable
/etc/init.d/unbound start


接下来配置dnsmasq,编辑dnsmasq的配置文件/etc/dnsmasq.conf,把指定的域名转发到unbound,用unbound进行解析。一行一个域名例如,

server=/xxx.com/127.0.0.1#5353

 

把被污染掉的域名加进去就可以了,重启dnsmasq生效。

此外还要配置dnsmasq的默认转发DNS地址,普通的dns请求继续用udp协议转发到运营商的DNS就可以,这样才能保证国内CDN网站正常使用,如下图。

Openwrt架设DNS转发器,解决污染问题_第1张图片

 

google上面有几个项目都可以获取到最新的污染域名列表,在这就不详细说了,哈哈。自己写了个脚本取下来,并通过计划任务定时更新,基本上都可以解决污染问题了。

以下放出脚本,具体不解释,该懂的都懂,需要使用完整版的wget。小tips:使用IPV6连接google code获取列表会方便很多。

make_dnsmasq_conf.sh

#!/bin/ash
#Anti DNS Pulltion
#make dnsmasq.conf
#Script By D2O
#
#v0.1 2012/8/13
#v0.2 2012/11/17

local DNS_DIR=/tmp/dns
local DNSMASQ_CONF=$DNS_DIR/dnsmasq.conf

wget --no-check-certificate -O $DNS_DIR/gfwlist.txt https://autoproxy-gfwlist.googlecode.com/svn/trunk/gfwlist.txt
wget -O $DNS_DIR/smarthosts http://smarthosts.googlecode.com/svn/trunk/hosts

echo please wait...
echo ##Anti DNS Pulltion >$DNSMASQ_CONF
$DNS_DIR/getlist.py $DNS_DIR/gfwlist.txt >>$DNSMASQ_CONF
#rm gfwlist.txt
#cp $DNSMASQ_CONF /etc/
/etc/init.d/dnsmasq reload


getlist.py,修改自网上大牛的脚本。

 

#!/usr/bin/env python
#	Aug 19 2011
#	Copyleft@2011 Published Under BSD Lisense
#			Ronald Liu
#	[email protected]
#	FYI  http://lzsblog.appspot.com/%3Fp%3D291001
#	

#	Mod By D2o 2012/8/13
#	http://conupefox.csdn.net

import sys,re,base64

def splitList(txt):
	arr = txt.split("\n")
	pattern ='^([01]?\d\d?|2[0-4]\d|25[0-5])\.([01]?\d\d?|2[0-4]\d|25[0-5])\.([01]?\d\d?|2[0-4]\d|25[0-5])\.([01]?\d\d?|2[0-4]\d|25[0-5])$'
	l = []
	for line in arr:
		if (not len(line)): #empty line
			continue
		if (line[0] == "!"): #Comment line
			continue
		elif(line[0:2] =="@@"):#Forbidding line
			continue
		elif(line.find("/")!=-1 or line.find("*")!=-1 or line.find("[")!=-1 or line.find("%")!=-1 or line.find(".")==-1 ): #URL is ignored, only domains left
			continue
		elif(re.search(pattern, line)):#IP address
			continue

		#In this case, domain name is irrelevant to protocol(http or https)
		elif(line[0:2] =="||"):
			l.append(line[2:])
		elif(line[0] == "."):
			l.append(line[1:])
		else:
			l.append(line)
	
	return l
	

#Decode and decorate the input string
f = open(sys.argv[1],"r")
txt = f.read()
txt = base64.decodestring(txt)
domains = splitList(txt)
per_line=""
forwarddns="127.0.0.1#5353"
for line in domains:
	if (line!=per_line):
		print "server=/" + line + "/" + forwarddns
	per_line=line


 

 

Enjoy!!

原文首发CSDN博客,转载请保留作者和出处,谢谢。

你可能感兴趣的:(dns,路由器,CDN,openwrt)