Dnsmasq 是 OpenWRT 系统默认内置的 DNS 解析器,要注意这个解析器不等同于 nslookup 和 dig,后面的只是调试工具,除了返回一些查询信息外不能给任何系统和应用提供解析结果,而 Dnsmasq可以。
Dnsmasq并不能算是一个DNS服务器软件,他的准确定义是一个DNS转发器。就是说,它把收到的DNS解析请求,转发到一些 DNS服务器上去,然后从DNS服务器接收返回的结果,最后再返回给你? 你也许会觉得我自己查询不好吗,干嘛要你来转发? 其实它能做的不仅仅是转发,转发仅仅是他实现 DNS查询的方式,我们知道它即不能递归查询,又不是迭代,能做的当然就是转发了。
首先它提供了一个缓存功能,这可以大大减轻你查询的网络请求次数,这也是为什么很多时候我们可以把他当一个DNS服务器来用的原因。除此之外Dnsmasq提供了非常多灵活的选项让我们可以完全掌控 DNS解析的行为。
1、 IPSET 功能
Dnsmasq从2.66版开始就支持 IPSET功能了,注意OpenWRT默认自带的 Dnsmasq是精简版本并没有 IPSET 功能,需要我们自己替换为 dnsmasq-full,也就是完整版。如果要确定自己的Dnsmasq 有没有 IPSET 功能支持,可以 SSH 登录路由后输入 “dnsmasq –version” 查看当前的版本和编译信息,可以看到下面的信息中已经包含了 ipset,如果显示的是 “no-ipset”,就说明没有 IPSET 功能支持。
root@OpenWrt :~# dnsmasq -- version
Dnsmasq version 2.71 Copyright (c) 2000 -2014 Simon Kelley
Compile time options : IPv6 GNU - getopt no -DBus no -i18n no -IDN DHCP DHCPv6 no -Lua TFTP no -
conntrack ipset auth DNSSEC
This software comes with ABSOLUTELY NO WARRANTY .
Dnsmasq is free software , and you are welcome to redistribute it
under the terms of the GNU General Public License , version 2 or 3.
这个功能的作用,就是把指定域名的解析结果存入一个 IP,具体哪些域名可以通过配置文件来指定。例如访问***,那么我们就把***.com的 IP都加入一个叫vpn的IPSET,然后配合我们前面学过的 iptables mark 功能,ip route 命令把对 *** IP 的访问全部通过 VPN 接口进行。我们的命令是这样的:
ipset =/ *** .com/vpn |
---|
非常令人感动的一点是,dnsmasq 是支持从顶级域往下匹配的,也就是说你写了***.com 之后,其二级三级四级域名也全部被匹配了,后面 “vpn” 就是我们事先通过 ipset 命令建立好的用于存储这些 IP 的 IPSET。
你也许会想,网站那么多IP,Dnsmasq能全部都查到? 查不到! 可是也完全没必要查到。因为你能用到的 IP就是 DNS 解析给你的 IP,其他的 IP 如果你连解析都没去解析他,为什么要知道呢?
这其实也就是 FreeRouter V2里相对 V1最优美的地方了,只有在你需要访问某个被封锁的IP时它才会起作用,而且具体什么IP可能被封锁是完全由你自己指定的,因为域名是你指定的。在 FreeRouter V1里这一切是通过静态路由表的方式实现的,这种方法的缺点是:
1. 要精确搜集一个网站的全部子域名和对应的全部IP极度困难
2. 以为精确搜集很难,所以经常不得不把整个网段加入静态路由表,但整个网段中有很多IP其实是没问题的
3. 很多IP对应的网站普通人听都没听过,这辈子可能也都不会上,但是如果不加注释的话,你根本不知道IP对应的到底是什么网站
4. 因为IP的可读性太差,如果根本就停掉了,要找出网站对应的IP再删除都很繁琐
而用 Dnsmasq 的 IPSET 功能就完全没有这种问题了。
2、为 Dnsmasq 指定 DNS
Dnsmasq 其实是一个 DNS 转发器,只是把我们的 DNS 解析请求转发到各个公共 DNS 上,那么我们就必须为 Dnsmasq 指定好使用哪些 DNS。
在 OpenWRT 系统中,Dnsmasq 的默认 DNS 服务器来源是通过在/etc/config/dhcp 文件中配置实现的:
config dnsmasq
option domainneeded '1'
option boguspriv '1'
option filterwin2k '0'
option localise_queries '1'
option rebind_protection '1'
option rebind_localhost '1'
option local '/lan/'
option domain 'lan '
option expandhosts '1'
option nonegcache '0'
option authoritative '1'
option readethers '1'
option leasefile '/tmp/。dhcpleases '
option resolvfile '/tmp/ resolv .。confauto '
我们看到最后一行是 resolvfile,查一下 Dnsmasq 的 Man Page 就会看到 Dnsmasq 会通过读取这个选项中指定的文件来获取 DNS 服务器列表,如果没有通过这个选项指定 DNS 服务器的配置文件的话,dnsmasq 默认会去读取/etc/resolv.conf 文件读取 DNS 服务器列表。
我们再看看这个/etc/resolv.conf。auto 文件的内容,不同设备可能有区别,但格式基本如此:
# Interface WAN
nameserver 8.8.8.8 nameserver 。。。8844
# Interface VPN
nameserver 8.8.8.8 nameserver 。。。8844
这个数据是怎么来的呢? 原来当我们的每一个网络接口成功连接上之后 (interface up),如果这个接口上有配置 DNS 服务器,或者 DHCP 服务器通告了 DNS 服务器,就会在这个文件里写入这个接口的 DNS 服务器。
如果我们要指定 DNS 服务器,而不是让 Dnsmasq 自动从各个接口获取 (因为 ISP 分配给我们的 DNS 基本都是被污染的),最简单也是最简陋的方法就是手工在每个接口的配置界面中指定 DNS,这样自动获取到的也是我们指定的 DNS。但是如果网络环境发生了变化,或者需要重新设置接口,就又要重新设置一次。而且这实际上就修改到了/etc/config/network 文件,倒不是说不能这样改,只是每个人的网路环境是不同的,这个文件也会因人而异,这样让我们很难提供一个统一的解决方案。
还有一个方法就是修改/etc/config/dhcp 文件,把最后的 resolvefile 选项改成我们指定的文件,然后在那个文件里写入 DNS 服务器列表,但是和上面的原因一样,修改 config 目录的文件会导致无法提供统一的解决方案。
最后我发现 dnsmasq 提供了一个参数叫做 “no-resolv”,这个选项允许不从任何文件中读取 DNS 服务器列表,改用 server 参数手工指定 DNS 服务器。这个时候我们就只需要在 Dnsmasq.conf(Dnsmasq 的配置文件) 中写如下命令就可以了:
# disable resolv file
no - resolv
server =8.8.8.8
井号 “#” 开始的部分是注释代码,会被 Dnsmasq 忽略掉,no-resolv 就是不读取任何任何列表文件, server=8.8.8.8 就表示用 8.8.8.8 作为一个 DNS 服务器。
如果我们想知道 Dnsmasq 到底使用了什么 DNS 服务器,可以先重启 Dnsmasq 服务:
/etc/。initd / dnsmasq restart
然后通过 “logread” 命令查看 dnsmasq 启动过程的记录,所有用到的 DNS 服务器信息都会显示出来。