在 CentOS 上使用 Dnsmasq 实现 DNS 转发

之前在  VPS 上搭建了 SS 服务器,但是由于 VPS 本身问题,国内访问并不快,一直也就这样用了。直到前段时间无意中发现了有 KCP 的存在,可以大大加快 SS 的访问速度,于是搞起,并把家里的路由器也搭建了 SS 客户端。因为在路由器上的代理方案选择了 dnsmasq + iptables 方案,通过 dnsmasq 查询目标网址的真实 IP 地址,iptables 负责将目标 IP 转发到 SS 服务器,因此,我需要在 VPS 上再搭建一个 dns 服务器。网上方案有两种(好像),这里我们选择和路由器一样的方案 dnsmasq。鉴于网上教程很多,这里只是做一个归纳总结。

dnsmasq 对 dns 的解析其实就是转发,所谓转发,就是通过 dnsmasq 查询 dns 记录时,会转发给其上级 dns 服务器并返回查询结果;同时,dnsmasq 有个很厉害的功能 —— 缓存。可以将上级 dns 服务器返回的结果,做一定时间的缓存,在缓存期间再次请求这条解析记录,会直接返回缓存结果。因为没有再次查询上级 dns 服务器,所以速度上也会快很多。

系统环境

  • CentOS 6.5 x64
  • Dnsmasq 2.66 (自带 yum 仓库中的版本)

安装 Dnsmasq

在 CentOS 里面安装 dnsmasq 非常简单,只需要一个指令即可:

[root@Singapore ~]# yum install dnsmasq -y

启动 dnsmasq 并设置开机自启动

在 CentOS 里面将一个服务设置成开机自启动也是非常简单的,如下:

[root@Singapore ~]# service dnsmasq start
[root@Singapore ~]# chkconfig dnsmasq on

第一行负责启动,第二行负责设置为开机自启动。

防火墙放行

如果你安装了 iptables 的话,那么需要让 iptables 放行其他电脑对本机 53 端口的访问,也只需要执行以下指令:

[root@Singapore ~]# iptables -I INPUT -p tcp --dport 53 -j ACCEPT
[root@Singapore ~]# iptables -I INPUT -p udp --dport 53 -j ACCEPT
[root@Singapore ~]# service iptables save

提醒:注意上面红字加粗的 53 端口是 DNS 服务器的默认端,如果你的服务器只是当做国内 dns 解析,那么你可以直接用 53 端口;但是!但是如果你搭建dns服务器是为了翻墙的话,那么你就不能设置53端口了,因为如果你这么做了,会很快被 GFW 检测到,到时把你的服务器 IP 加入黑名单你就哭吧。

配置监听地址和上级 DNS 服务器地址

上面的步骤完成后,实际上你的 dnsmasq 已经可以对外提供服务了,但是我们还没有对它进行配置。编辑 /etc/dnsmasq.conf 配置文件,在最末尾加入:

# 自己服务地址,不支持 0.0.0.0 广域网广域网方式
listen-address=127.0.0.1,x.x.x.x 
server=8.8.8.8
server=8.8.4.4
# 若想改一个端口(默认端口为53)的话,可以增加下面这个设置项
port=5353

然后保存退出,这样你的 dnsmasq 就会去响访问它的 dns 请求,并且去 8.8.8.8 和 8.8.4.4 这两个上级 dns 服务器查询结果并缓存。

重新启动 dnsmasq

[root@Singapore ~]# service dnsmasq restart

测试一下是否正常

若您的 CentOS 服务器已经安装了 bind-utils 组件包,那么就可以使用 dig 指令对 dns 服务器进行测试。若没有安装 bind-utils 组件包的话,可以通过以下指令进行安装:

[root@Singapore ~]# yum install bind-utils -y

安装完毕后,就可以使用 dig 指令来测试一下刚刚构建的 dnsmasq 是否正常啦~

[root@Singapore ~]# dig @127.0.0.1 www.google.com.hk

执行第一次如果能看到返回正确的 IP 地址,那么就算成功了,比如:

[root@Singapore ~]# dig @127.0.0.1 www.google.com.hk

; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.37.rc1.el6_7.6 <<>> @127.0.0.1 www.google.com.hk
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 43393
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;www.google.com.hk.        IN  A

;; ANSWER SECTION:
www.google.com.hk.    299 IN  A   74.125.200.94

;; Query time: 57 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Sun Feb 28 09:05:43 2016
;; MSG SIZE  rcvd: 51

你会留意到,第一次查询的查询时间(Query time)为 57 毫秒,那么再试着重复执行一次指令,来看看第二次查询相同的域名需要多长时间才能有结果…

[root@Singapore ~]# dig @127.0.0.1 www.google.com.hk

; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.37.rc1.el6_7.6 <<>> @127.0.0.1 www.google.com.hk
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 2730
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;www.google.com.hk.        IN  A

;; ANSWER SECTION:
www.google.com.hk.    230 IN  A   74.125.200.94

;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Sun Feb 28 09:06:52 2016
;; MSG SIZE  rcvd: 51

因为缓存的原因,第二次的查询时间为 0ms ...