共计 7486 个字符,预计需要花费 19 分钟才能阅读完成。
还是出于项目的需要,把 Bind 比较高级的功能做一个梳理,这其中包含:DNS 递归迭代查询、DNS 子域授权、DNS 转发、DNS 主从区域传输、DNS 数据加密,每一个内容不仅记录了它的实现原理,也相应的配上了我一行一行代码的实践测试及结果。
所有的测试都是基于我原来的文章:Bind 服务搭建及测试上的代码来进行的,所以下面的代码如果有不理解的,请去看看我之前写的文章。
DNS 递归迭代查询
为什么要把 DNS 的查询称之为递归迭代查询:
递归是因为:
用户端向我的服务端发起一次查询请求,那么服务端如果有结果就返回,如果没有结果就像上一级服务器再发一次请求,直到找到用户需要的 IP 或者域名,这个过程可以称之为递归。
迭代是因为:
当服务端向上一级服务器法请求的时候,它并不是一次请求就结束了,先是根域,再是二级域名这样了,有多次的请求跟返回动作,这个过程可以称之为迭代。
我在 Bind 搭建及测试这篇博文里面,对它们的流程做了更详细的叙述,这里就不多写了。
参数
Bind 既然有一个复杂的查询流程,那么与之相对应的就会有一系列的配置项来控制这个流程。下面讲的参数都是基于 Bind 的主配置文件 named.conf。
- recursion : {yes|no} 是否允许递归请求
- allow-recursion : {address_match_list|any|none} 允许递归请求的范围
- recursion-clients : {number(填数字)} 客户端执行递归请求的数量
测试
named.conf 配置文件的内容如下所示:
options {
directory "/var/named";
recursion yes;
};
zone "." {
type hint;
file "named.ca";
};
zone "liumapp.com" {
type master;
file "liumapp.com.zone";
};
zone "cnametest.com" {
type master;
file "cnametest.com.zone";
};
zone "32.29.115.in-addr.arpa" {
type master;
file "115.29.32.zone";
};
可以看到,我默认是把递归查询开启的
开启递归的情况
随便查询一个域名,比如“www.qqq.com”
可以发现,Bind 为了找到 www.qqq.com 对应的 IP 地址,往上层域名服务器迭代了 7 次才找到最终结果。
关闭递归的情况
现在我们将配置文件的 recursion 改为 no,重启 Bind 之后再查询一个新的域名,比如 ”www.qqqq.com”(www.qqq.com 已经做了缓存)
可以看到,关闭递归后我们是查不到新域名的解析记录的。
DNS 子域授权
在 DNS 迭代查询的情况下,经常会用到 NS 记录,同样的,在 DNS 子域授权下面,NS 记录也会经常被用到。
子域授权:
比如我的一台服务器 A 负责 liumapp.com 的权威域名解析,它再授权服务器 B 对 liumapp.com 的子域名:child.liumapp.com 进行解析,这就叫做子域授权。
DNS 迭代查询利用的就是子域授权:通过根域,到二级域再依次往下迭代查询。
测试
我的父服务器 IP 为 115.29.32.62,其解析的域名为 www.liumapp.com,子服务器 IP 为 106.14.212.41,其解析的域名为 www.test.liumapp.com
首先在父服务器上,我们要对子服务器进行授权,具体配置 liumapp.com.zone 文件,添加如下内容:
test.liumapp.com. IN NS ns1.test
ns1.test IN A 106.14.212.41
大意就是给 liumapp.com 的子域名 test.liumapp.com 分配权限给 ns1.test,然后指定 ns1.test 的 IP 为 106.14.212.41
重启父服务器,然后进入子服务器的 shell 命令面板
首先我们对 named.conf 做一个备份,然后把它的内容修改为:
options {directory "/var/named";};
zone "test.liumapp.com" {
type master;
file "test.liumapp.com.zone";
};
然后在 /var/named/ 目录下添加一个 test.liumapp.com.zone 文件,其内容为:
$TTL 7200
@ IN SOA test.liumapp.com. liumapp.com.gmail.com. (222 1H 15M 1W 1D)
@ IN NS dns1.liumapp.com.
dns1.liumapp.com. IN A 106.14.212.41
www.test.liumapp.com. IN A 106.14.212.42
接下来重启 Bind。
然后我们进行测试,首先对父服务器进行解析:
dig @115.29.32.62 www.test.liumapp.com
结果为:
然后我们对子服务器进行解析:
dig @106.14.212.41 www.test.liumapp.com
结果为:
DNS 转发
概念
假设有一个局域网,内部有两台 DNS 服务器,命名为 A 和 B,局域网通过防火墙对外开放,但是只有 A 能够直接对外提供 DNS 解析服务,B 只能在局域网内的内网进行访问,那当需要用到 B 的 DNS 解析的时候,就是通过 A 的 forwarding 转发来实现。
配置
首先看一下关于转发的配置项
- forwarders : {address_list} 表示转发的服务器列表
- forwarder only : 表示只由目的服务器权威解析
- forwarder first : 优先转发查询
测试
同样是父服务器 115.29.32.62 和子服务器 106.14.212.41,我们现在把父服务器用来负责 DNS 的某一个域作为转发,子服务器用来负责某一个域的权威解析。
现在我们先配置子服务器的权威解析:
首先进入 /var/named 目录,新建一个文件 dnstest.com.zone(这个域名我并没有拥有它,只是为了测试方便随便写的),其内容为:
$TTL 7200
@ IN SOA dnstest.com. liumapp.com.gmail.com. (222 1H 15M 1W 1D)
@ IN NS dns.dnstest.com.
dns.dnstest.com. IN A 106.14.212.41
www.dnstest.com. IN A 6.6.6.6
然后修改 named.conf,添加下列内容:
zone "dnstest.com" {
type master;
file "dnstest.com.zone";
};
同时删除原来的
zone "test.liumapp.com" {
type master;
file "test.liumapp.com.zone";
};
重启 Bind。
然后进入父服务器的 shell 操作面板,在开始之前,我们要注意一点,就是 Bind 的 DNS 转发只有在 Bind9 版本以上才支持,所以在开始之前,我们先使用命令查看一下 Bind 的版本:
nslookup -q=txt -class=CHAOS version.bind
我的服务器上出来的结果是:
[root@iZ28vhwdq63Z ~]# nslookup -q=txt -class=CHAOS version.bind.
Server: 10.202.72.116
Address: 10.202.72.116#53
version.bind text = "9.9.9-P3-RedHat-9.9.9-2.1.alios6"
然后修改 named.conf,添加以下内容:
zone "dnstest.com" {
type forward;
forwarders {106.14.212.41;};
}
接下来我们在父服务器上使用 dig 命令:
dig @127.0.0.1 www.dnstest.com
请求解析 www.dnstest.com 域名,结果如下:
同时要注意,forward 的正常使用需要递归查询 recursion 开启。
DNS 主从区域传输
区域是 DNS 服务器的管辖范围, 是由 DNS 名称空间中的单个区域或由具有上下隶属关系的紧密相邻的多个子域组成的一个管理单位。因此, DNS 名称服务器是通过区域来管理名称空间的, 而并非以域为单位来管理名称空间, 但区域的名称与其管理的 DNS 名称空间的域的名称是一一对应的。或者说,一个区域对应一系列域名的解析。
DNS 主从同步
假设我们有两台服务器,分别为 dns 主服务器 Master 和 dns 从服务器 slave,那么他们之间的 dns 主从同步步骤是这样的:
- master 发送 notify 信息给 slave
- slave 去查询主服务器的 SOA 记录
- master 将 SOA 记录发送给 slave
- slave 根据 SOA 记录去检查 serial number 是否有递增更新
- 如果有的话 slave 向 master 发起 zone transfer 请求,然后 master 返回响应结果,slave 更新记录。如果没有的话就说明不需要更新。
DNS 主从配置
在开始配置之前,先要注意几个事项:
- 确保防火墙的规则不会拦截 Bind 的监听端口,默认为 53
- 确保 named 用户拥有操作相关目录的权限(/var/named)
- 确保主从服务器的时钟一致
- 搭建完毕后,若修改主服务器域的配置,serial number 必须递增
服务器配置
Master 服务器
zone "liumapp.com" {
type master;
notify yes;
also-notify{106.14.212.41;};
file "liumapp.com.zone";
}
上面的 notify yes 表示开启 notify 这个功能,also-notify{} 里面放的是 slave 服务器的 IP 列表。
Slave 服务器
options{
directory "/var/named";
allow-query {any;};
recursion yes;
};
zone "liumapp.com" {
type slave;
file "slaves/liumapp.com.zone";
masters {115.29.32.62;};
};
上面的 file 表示从主服务器同步过来的信息存放地址,我这里就表示存放在 /var/named/slaves/liumapp.com.zone
我把 IP 为 115.29.32.62 的 dns server 作为我的 master,IP 为 106.14.212.41 的 dns server 作为我的 slave。
首先我们按照上面两段代码进行主从服务器的配置。
然后重启两台服务器的 Bind,重启之后,应该就能够在从服务器的 /var/named/slaves/ 下找到一个 liumapp.com.zone 文件,它的内容应该跟主服务器的 /var/named/liumapp.com.zone 一致。
所以,这个时候我们不管使用命令
dig @115.29.32.62 www.liumapp.com
向主服务器请求 www.liumapp.com 的解析还是
dig @106.14.212.41 www.liumapp.com
向从服务器请求 www.liumapp.com 的解析,得到的结果最终都是一样的。
测试
现在我们按照上面的配置走完了一遍之后,来测试一下主从服务器之间的同步。
在 Master 服务器的 /var/named/liumapp.com.zone 文件上,我们添加一条解析记录:
liumei.liumapp.com. IN A 8.8.5.6
然后添加一下它的 serial number 值,也就是:
liumapp.com. IN SOA liumapp.com. liumapp.com.gmail.com8 (225 1H 15M 1W 1D)
这条记录里面的倒数第 5 个数“225”,我们把它改为 226 即可。
重启服务器之后,敲命令:
dig @106.14.212.41 liumei.liumapp.com
即可成功在子服务器上解析到 liumei.liumapp.com 的记录为 8.8.5.6
DNS 区域传输限制
首先,我们在本地一台电脑上使用一个命令:
dig @115.29.32.62 axfr liumapp.com
不出意外,应该能够得到 liumapp.com 在 115.29.32.62 这台 DNS server 上的所有解析记录
但是从安全角度来讲,我肯定不希望这样的事情发生,所以就要用到传输限制。
方法
-
基于主机的访问控制
通过主机 IP 来限制访问。
- allow-transfer : {address_list | none} , 允许域传输的机器列表
- 事务签名
通过密钥对数据进行加密。
事务签名的测试我会放在后面的 DNS 数据加密里面来做。
测试
我们在主服务器上的 named.conf 配置文件中进行修改:
zone "liumapp.com" {
type master;
notify yes;
also-notify {106.14.212.41;};
allow-transfer{106.14.212.41;};
file "liumapp.com.zone";
};
重启 Bind 之后,回到本地电脑上,继续使用命令:
dig @115.29.32.62 axfr liumapp.com
结果如下,请求已被拒绝。
但是通过 106.14.212.41 是可以获取数据的:
dig @106.14.212.41 axfr liumapp.com
结果如下:
DNS 数据加密
加密方式
-
DES 对称加密
- 概述:文件加密和解密使用相同的密钥,简单快捷。
- 流程:假定有发送方 A 和接收方 B,A 和 B 有相同的密钥,A 发送明文给 B 之前,通过密钥和加密算法,将明文加密成密文,发送给 B,B 再通过密钥和解密算法,将密文解密成明文。
-
IDEA 非对称加密
- 概述:密钥包括公钥和私钥,安全性较 DES 方式高。
- 流程:假定有发送方 A 和接收方 B,B 有自己的私钥和公钥,A 需要获取 B 的公钥,获取之后,A 首先自己生成一个会话密钥,然后这个会话密钥通过 B 的公钥进行加密,加密后发送给 B,B 再通过自己的私钥对它进行解密,从而得到 A 生成的会话密钥。之后,A 通过自己的会话密钥将要发送的明文进行加密,发送给 B,B 通过事先得到的会话密钥对发送过来的密文进行解密从而得到明文。
DNS 事务签名
事务签名可以通过两种加密方式来实现,分别是:
- TSIG: 对称方式
- SIGO: 非对称方式
现在比较常用的是 TSIG 这种方法。
TSIG 事务签名
参数:
- allow-transfer : {key keyfile}(key 及 key 的文件位置); 事务签名的 key
测试
首先我们进入主服务器,然后生成 key:
在主服务器的 /usr/key 目录下,注意赋予 key 目录 named 用户的读权限
输入以下命令:
dnssec-keygen -a HMAC-MD5 -b 128 -n HOST liumapp-key
- -a : 加密算法
- -b : 加密位数
- -n : 可以选择 ZONE 或者 HOST
- liumapp-key: 密钥名称
我生成的公钥文件和私钥文件其内容如下所示:
然后我们复制私钥里面的那段 key 的内容,再进入 /var/named/chroot/etc 目录,新建一个 liumapp-key 文件
其内容为:
key "liumapp-key" {
Algorithm hmac-md5;
secret "ghWgud4mhN11PKBIITgxbg==";
};
上面的 secret 的值是从生成的私钥文件中复制来的。
然后编写 named.conf 文件,添加以下内容:
include "/var/named/chroot/etc/liumapp-key";
注意,这段内容要放在 zone “liumapp.com” 之前。
然后修改 zone “liumapp.com” 的配置,最终配置结果如下:
include "/var/named/chroot/etc/liumapp-key";
zone "liumapp.com" {
type master;
notify yes;
also-notify {106.14.212.41;};
allow-transfer{key "liumapp-key";};
file "liumapp.com.zone";
};
上面的 allow-transfer 的 key 的值是我命名的那个值。
然后我们重启 Bind,接下来是配置 slave 从服务器,不过在配置之前,需要先把我们的配置文件 liumapp-key 拷贝过去:
使用命令:
scp liumapp-key root@106.14.212.41:`pwd`
结果如下所示:
然后在从服务器的 named.conf 中进行配置,一个是把 liumapp-key 包含进去,然后配置 key,最终结果如下所示:
options{
directory "/var/named";
allow-query {any;};
recursion yes;
};
include "/var/named/chroot/etc/liumapp-key";
server 115.29.32.62 {keys {"liumapp-key";};
};
zone "dnstest.com" {
type master;
file "dnstest.com.zone";
};
zone "liumapp.com" {
type slave;
file "slaves/liumapp.com.zone";
masters {115.29.32.62;};
};
重启从服务器的 Bind 服务,然后我们再回到主服务器:
添加一条 liumapp.com.zone 下的 A 记录,当然还需要递增一下 serial number 也不知道加了多少,总之最后我的这个 ZONE 的内容如下所示:
$TTL 7200
liumapp.com. IN SOA liumapp.com. liumapp.com.gmail.com8 (226 1H 15M 1W 1D)
liumapp.com. IN NS dns1.liumapp.com.
dns1.liumapp.com. IN A 115.29.32.62
www.liumapp.com. IN A 106.14.212.41
liumei.liumapp.com. IN A 8.8.5.6
heiheihei.liumapp.com. IN A 9.9.9.9
@ IN MX 10 mail
mail IN A 115.29.32.63
test.liumapp.com. IN NS ns1.test
ns1.test IN A 106.14.212.41
然后重启 bind,再使用命令:
tail -f /var/log/messages
得到的信息如下所示:
可以看到,我修改了 liumapp.com.zone 之后,主服务器马上同步到了从服务器上,而他们之间的交流,就是用到了 TSIG 事务签名。