之前详细介绍了DNS及其在linux下的部署过程,今天再说下DNS的BIND高级特性-forwarder转发功能。比如下面一个案例:
1)已经在测试环境下部署了两台内网DNS环境,DNS的zone域名为kevin.cn:http://www.cnblogs.com/kevingrace/p/5570312.html
2)测试机器的DNS地址已经调整为这两台DNS地址,所以测试机访问kevin.cn域名是没有问题的。
  由于业务需求,需要测试机器能访问grace.cn域名(grace.cn域名是使用别的DNS地址解析的),这就用到了DNS的BIND中的forwarder转发功能了。
  通过BIND的forwarder转发功能,将测试机访问的非kevin.cn的域名都转向forwarder指定的DNS地址上。

forwarder转发功能只需要在named.conf中配置即可:
[root@uatdns01 ~]# cat /etc/named/named.conf
options {
             listen-on port 53 { any; };
             listen-on-v6 port 53 { ::1; };
             directory "/var/named";
             dump-file       "/var/named/data/cache_dump.db";
             statistics-file "/var/named/data/named_stats.txt";
              memstatistics-file "/var/named/data/named_mem_stats.txt";
              allow-query     { any; };
              recursion yes;
              forward first;
              forwarders {            #即访问非kevin.cn域名时将解析转发到这几个DNS地址(分别为阿里的DNS、google的DNS)上进行解析。
                     223.5.5.5;          #注意这里转发的是DNS地址,没有指定DNS转发域名。
                     223.6.6.6;
                     8.8.8.8;
                     8.8.4.4;
               };
               };

logging {                            
             channel default_debug {
             file "data/named.run";
             severity dynamic;
             };
};

zone "." {
              type hint;        
              file "named.ca";  
       };

zone "kevin.cn" {                      
              type master;                            
              file "kevin.cn_zone";            
};
zone "51.168.192.in-addr.arpa" {        
              type master;
              file "192.168.51.zone";              
};

zone "50.168.192.in-addr.arpa" {
              type master;
              file "192.168.50.zone";
};

zone "104.168.192.in-addr.arpa" {
              type master;
              file "192.168.104.zone";
};
zone "grace.cn" {                       #访问grace.cn域名时,将解析请求转到192.168.51.39(即grace.cn域名的DNS地址),注意这个不能写在上面的forwarder处,否则转发无效!
              type forward;                #注意这里转发配置中制定了转发的域名,即forwad转发区(forward zone)设置,这是bind9之后的新特性。
              forwarders { 192.168.51.39; };
};

========================================================================
尝试了下,无法在一个named.conf里同时配置两个或多个域的zone(即正向解析的zone),配置好并重启named服务器后,多出的那个域名解析无效。
比如内网有两个域名:kevin.cn和grace.cn,要做这两个域名的DNS解析环境,实现方案如下:

1)分别针对kevin.cn和grace.cn部署两套DNS环境
2)在其中一个域名的DNS环境中使用forwadr转发,比如在kevin.cn域名的named.conf配置中添加:
     zone "grace.cn" {                       
              type forward;                
              forwarders { 192.168.51.39; };           # 该ip为grace.cn域名的DNS服务器地址
     };
3)将客户机的DNS(/etc/resolv.conf)配置成kevin.cn域名的DNS地址,这样该客户机对于kevin.cn和grace.cn域名都可以解析。

===========================BIND之forwarder转发功能小结======================
forward first | only;
forward指令用于设置DNS转发的工作方式:
1)forward first设置优先使用forwarders DNS服务器做域名解析,如果查询不到再使用本地DNS服务器做域名解析。
2)forward only设置只使用forwarders DNS服务器做域名解析,如果查询不到则返回DNS客户端查询失败。

最新版的BIND提供了很多非常好的DNS新特性,其中一个就是Forwarder转发功能:

总所周知,某些网络连接是不鼓励向本地以外发送很大的数据流量的,因为网络连接是按流量计费的,并且网络连接本身是带宽不足。在这样的情况下,如果想将发往外部的DNS流量限制到尽可能的小,就需要使用BIND的转发机制。或者网络中只有一台机器能连接到Internet ,而在这台机器上运行了 BIND ,那么可以将这台BIND作为内部网络中的其他BIND的转发器,使得其他DNS也能查找Internet域名。
BIND的forward转发机制的这样的:
当设置了forwarders转发器后,所有非本域的和在缓存中无法找到的域名查询都将转发到设置的DNS转发器上,由这台DNS来完成解析工作并做缓存,因此这台转发器的缓存中记录了丰富的域名信息。因而对非本域的查询,很可能转发器就可以在缓存中找到答案,避免了再次向外部发送查询,减少了流量。

转发器的配置格式是:
options {  
            forwarders { 192.168.10.35; 192.168.10.36; };
};

这里需要注意的是:
转发器本身不用做任何设置,而是对需要转发器的其他DNS server做以上配置。还有,如果该DNS Server无法联系到转发器,那么BIND会自己尝试解析。

如果要禁止BIND在无法联系到转发器时不做任何操作,那么还可以使用forward only命令,这样BIND只能使用区的权威数据和缓存来响应查询了(在连接不到转发器的情况下)。
options {  
            forwarders { 192.168.10.35; 192.168.10.36; };
            forward only;
};

=======================================================================
在BIND8.2以后引入了一个新的特性:转发区(forward zone),它允许把DNS配置成只有查找特定域名的时候才使用转发器。( BIND 9从9.1.0才开始有转发区功能 )例如,你可以使你的服务器将所有对 kevin.cn 结尾的域名查询都转发给 kevin.cn 的两台名字服务器:
zone "kevin.cn" {
          type forward;
          forwarders { 110.50.80.208; 110.50.80.209; };
};

这样的功能有什么用呢?
假设kevin.cn和你的网络有一个私有的连接,而kevin.cn又没有连接上Internet ,那么你从Internet 是无法查到 kevin.cn 后缀的域名的,这时你就要使用转发区的功能了。

还有一种转发区设置和刚才的设置刚好相反,它允许设置什么样的查询将不被转发,当然这只适用于在options语句中指定了转发器的DNS 。配置如下:
options {  
            directory "/var/named";    
            forwarders { 192.168.10.35; 192.168.10.36; };
};

zone "kevin.cn" {
          type master;
          file "zone.kevin.cn";
          forwarders {};
};

这样写有人可能会问为什么要在自己的权威区里禁止转发?难道不是自己回答查询而不使用转发器吗?
这是因为有这样一种情况:在 kevin.cn这个区中,你授权了几个子域,例如:zx.kevin.cn、lab.kevin.cn 等,那么在kevin.cn的权威服务器上设置转发后,因为对 zx.kevin.cn、lab.kevin.cn 这几个子域不是权威,那么如果有对www.zx.kevin.cn这样的子域的域名查询,服务器也将转发。这完全是没有必要的,因为服务器上就有zx.kevin.cn 子域的NS记录,何须再转发。

假设我的DNS服务器 192.168.1.10,在BIND中有这么一个配置
forward only;
             forwarders {
            192.168.1.12;
};

这里的192.168.1.10解析不了的,就会被转发到192.168.1.12这就是DNS转发器。
说到这里就不得不说下BIND的递归功能了。

=====================BIND递归查询功能小结====================
默认 Resolver 发出的是递归查询,而且默认 BIND name server 也处理所有的递归请求。

递归查询的工作方式
递归查询是最常见的查询方式,域名服务器将代替提出请求的客户机(下级DNS服务器)进行域名查询,若域名服务器不能直接回答,则域名服务器会在域各树中的各分支的上下进行递归查询,最终将返回查询结果给客户机,在域名服务器查询期间,客户机将完全处于等待状态。
示例: (红色为查询,蓝色为迭代查询返回的提示信息,棕色为递归查询返回的IP信息)

DNS之BIND使用小结(Forward转发)_DNS

示例说明:
A向B发送递归查询请求,B向C发送迭代查询请求,得到C给出的提示后,B向D发送迭代查询请求,得到D给出的提示后,B向E发出迭代请求,得到E给出的提示后,B向F发出迭代查询请求,得到F给出的提示后,B得到了F返回G的IP地址,B向A返回G的IP地址,整个查询结束。

迭代查询的工作方式
迭代查询又称重指引,当服务器使用迭代查询时能够使其他服务器返回一个最佳的查询点提示或主机地址,若此最佳的查询点中包含需要查询的主机地址,则返回主机地址信息,若此时服务器不能够直接查询到主机地址,则是按照提示的指引依次查询,直到服务器给出的提示中包含所需要查询的主机地址为止,一般的,每次指引都会更靠近根服务器(向上),查寻到根域名服务器后,则会再次根据提示向下查找。从上节的图中可以知道,B访问C、D、E、F、G,都是迭代查询,首先B访问C,得到了提示访问D的提示信息后,开始访问D,这时因为是迭代查询,D又返回给B提示信息,告诉B应该访问E,依次类推。

说明:假设你要寻找一家你从未去过的公司,你会有2种解决方案:
1)找一个人替你问路,那可能是你的助手
2)自己问路,每走过一个路口,就问一个人,这就好比递归查询和迭代查询,递归查询在这里代表你的第1种解决方案,而迭代则是第2种解决方案。

但某些情况下,服务器应该被配置为不接受递归请求,例如根域服务器。根域服务器不接受递归请求的原因 :
1)因为根域服务器太忙了,它们没有精力来回答递归查询。
2)接受递归请求将会建立缓存,如此根域服务器的缓存将会变得十分巨大

关于递归/非递归方面的配置语句有recursion no和 allow-recursion 语句,两者都只能放在options或者view语句中;
recursion no只对外部域名有效,如果查询的是本地zone域名(仅限于该 name server 上所定义的 zone,不包括下级子域)则可以回答。因为解析外部域名需要查询外部 name server ,这才是 recursion no 控制和关心的部分,如果查询的是本地 zone 的数据,当然不需要担心本地 name server 被诱导,可以直接返回答案。

需要注意以下几点;
1)保证该非递归服务器不出现在客户机的 /etc/resolv.conf 的
2)证该非递归服务器不被其他 name server 当成转发器 (forwarder)
3)推荐使用 allow-recursion 而不是 recursion
4)该非递归服务器可以出现在 zone data file 的 NS 记录中。它可以正常的接收其他 name server 发来的查询
5)外部 name server 是通过上级域的 Referral 消息找到该非递归服务器的
6)外部 name server 在得到上级域的 Referral 消息后,向该非递归服务器发送的查询是 iterative query ,而不是 recusive query ,所以该非递归服务器仍然可以回答那些它所权威的 zone 的查询。但不能用于查询外部域名了。

============================BIND配置语法小结============================
下面罗列出/etc/named/named.conf 中使用的常用配置语句。named.conf 中使用的常用配置语句:

acl定义访问控制列表,参考 acl
controls定义 rndc 命令使用的控制通道,若省略此句,则只允许经过 rndc.key 认证的 127.0.0.1 的 rndc 控制,参考 rndc
include将其他文件包含到本配置文件当中
key定义用于 TSIG 的授权密钥
logging定义日志的记录规范,参考 BIND 9 的高级配置 的 “BIND 日志部分”
lwres将 named 同时配置成一个轻量级的解析器
options定义全局配置选项
trusted-keys为服务器定义 DNSSEC 加密密钥
server设置每个服务器的特有的选项
view定义域名空间的一个视图,参考 BIND 9 的高级配置 的 “View 语句部分”
zone定义一个区声明

下面对named.conf中常用的语句作进一步的说明。

include
include 语句的功能为:将指定的文件引入 named.conf 主配置文件。语法为:

include "path";
建议使用绝对路径
若使用相对路径,则相对于 directory 选项指定的目录
options
options 用于定义全局配置选项,语法为:

options {
         配置子句;
         配置子句;
};

下面列出一些常用的全局配置子句。

子句说明
directory “path”定义服务器区数据库文件的工作目录,配置文件中所有使用的相对路径,指的都是在这里配置的目录下。Ubuntu 默认为 /var/cache/bind
notify yes/no若 named 是主服务器,当区数据库变化时将自动通知相应区的从服务器,默认为 yes
recursion yes/no是否使用递归式  服务器,默认为 yes
transfer-format one-answer/many-anser设置从主服务器向从服务器复制数据的方式,使用在主域名服务器上,是否允许在一条消息中放入多条应答信息,默认值为 many-answer
forwarders {IPaddrs}设置全局转发器,列出要用作转发器的服务器 IP 地址
forward only/first若值为 only,则服务器缓存数据并查询转发器,但从不查询其他的任何服务器,若转发器不能响应查询则查询失败;若值为 first,则在转发查询失败或没有查到结果时,会在本地发起正常查询。默认为 first

zone 区声明是配置文件中最重要的部分。Zone 语句的格式为:
zone  "zone-name" IN {
         type  子句;
         file 子句;
         其他子句;
};

下面列出一些常用的 zone 配置子句。

子句说明
type master/slave/hint/forward说明一个区的类型。master:说明一个区为主域名服务器;slave说明一个区为辅助域名服务器;hint:说明一个区为根服务器的线索;forward:说明一个区为转发区
file “filename”说明一个区的域信息源数据库信息文件名

DNS 数据库
一个域的 DNS 数据库是由这个域的主域名服务器的管理员所维护的文本文件的集合。这些文件经常被称为区文件,区文件定义了一个区的域名信息。Ubuntu 默认将区文件存放在 /var/cache/bind 目录下。

每个区文件都是由若干个资源记录(RR,resource records)和分析器指令所组成。

资源记录简介
标准资源记录的基本格式是:
[name]  [ttl]  [class]  type  data

各个字段之间由空格或制表符分隔,字段可以包含如下的特殊字符:
; — 引出注释
@ — 表示当前域
() — 允许数据跨行,通常用于 SOA 记录
* — 仅用于 name 字段的通配符

name 字段
name 字段说明资源记录引用的对象名,可以是一台单独的主机也可以是个域名。
对象名可以是相对域名或全域名,全域名应该以“.”结束
若几条连续的 RR 记录涉及同一个对象名,则第一条 RR 记录后的 RR 记录可以省略对象名
若出现字段名字段,则必须出现在第一个字段
关于相对域名和全域名:举例来说,在 ubuntu.org.cn 域中,相对域名 osmond 与全域名 osmond.ubuntu.org.cn. 等效;而 osmond.ubuntu.org.cn 由于没有以“.”结尾,被认为是一个相对域名,与其等效的全域名为 osmond.ubuntu.org.cn.ubuntu.org.cn.。因此在书写对象名时要特别小心。

ttl 字段
ttl(time to live) 字段是一个寿命字段。它以秒为单位定义该资源记录中的信息存放在高速缓存中的时间长度。通常省略该字段,而使用位于文件开始处的 $TTL 语句所指定值。

class 字段
class 字段用于指定网络类型,可选的值有:IN、CH 和 HS,其中 IN (Internet)是广泛使用的一种。虽然 IN 是该字段的默认值,但通常我们会显示地指出。

type 字段
type 字段用于说明 RR 的类型。常用的 RR 类型如下:

DNS之BIND使用小结(Forward转发)_DNS_02

关于RR 的书写顺序
SOA RR 应该放在最前面
通常 NS RR 紧跟在 SOA RR 之后
其他记录的顺序无关紧要

data 字段
data 字段的内容取决于 RR 的类型字段。

常用的资源记录
SOA 资源记录
SOA RR 用于标示一个区的开始,其格式如下:

zone      IN      SOA   Hostname  Contact (
              SerialNumber
              Refresh
              Retry
              Expire
              Minimum )

SOA 记录的数据说明
Hostname
存放本 Zone 的域名服务器的主机名
Contact
管理域的管理员的邮件地址
SerialNumber
本区配置数据的序列号,用于从服务器判断何时获取最新的区数据
Refresh
辅助域名服务器多长时间更新数据库
Retry
若辅助域名服务器更新数据失败,多长时间再试
Expire
若辅助域名服务器无法从主服务器上更新数据,原有的数据何时失效
Minimum
设置被缓存的否定回答的存活时间

如下示例:

kevin.cn.     IN      SOA   wang.kevin.cn.  root.wang.kevin.cn. (
                              2006063000       ;序列号
                              3H               ;3小时后刷新
                              15M              ;15分钟后重试
                              1W               ;1星期后过期
                              1D )             ;否定缓存TTL为1天

对 Contact 来说,因为“@”在文件中有特殊含义,所以邮件地址 root@wang.kevin.cn 写为 root.wang.kevin.cn.
对 SerialNumber 来说,它可以是 32 位的任何整数,每当更新区文件时都应该增加此序列号的值,否则 named 将不会把区的更新数据传送到从服务器
缓存时间字段 Refresh、Retry、Expire、Minimum 可以使用时间单位字符 m、h、d、w 分别表示分钟、小时、天、星期。
各个缓存时间字段的经验值为:
Refresh — 1 到 6 小时
Retry — 20 到 60 分钟
Expire — 1 周 到 1 月
Minimum — 1 到 3 小时
Minimum 设置被缓存的否定回答的存活时间,而肯定回答(即真实记录)的默认值是在区文件开始处用 $TTL 语句设置的。

NS 资源记录
NS RR 用于标识一个区的权威服务器(包括主服务器和从服务器),并将子域授权赋予其他服务器,其格式如下:
zone    [ttl]    IN    NS    hostname

示例如下:

kevin.cn.          IN    NS    wang.kevin.cn.             #指定 kevin.cn. 的主服务器
kevin.cn.          IN    NS    dapper.kevin.cn.           #指定 kevin.cn. 的从服务器
osmond.kevin.cn.   IN    NS    ubuntu.osmond.kevin.cn.    #指定委派域 osmond.kevin.cn. 的主服务器
osmond.kevin.cn.   IN    NS    dapper.osmond.kevin.cn.    #指定委派域 osmond.kevin.cn. 的从服务器

若上面的记录紧跟在 SOA 记录后,也可以写成如下的形式:

IN    NS    wang.kevin.cn.                    #指定 kevin.cn. 的主服务器
          IN    NS    dapper.kevin.cn.        #指定 kevin.cn. 的从服务器
osmond    IN    NS    ubuntu.osmond.kevin.cn. #指定委派域 osmond.kevin.cn. 的主服务器
osmond    IN    NS    dapper.osmond.kevin.cn. #指定委派域 osmond.kevin.cn. 的从服务器

A 资源记录
A RR 是 DNS 数据库的核心,它提供了主机名到 IP 地址的映射。其格式为:
hostname    [ttl]     IN     A     IPAddress

对于 kevin.cn 区来说, 如下示例:

wang            IN    A      192.168.0.251
dapper          IN    A      192.168.0.252
wang.osmond     IN    A      192.168.1.251
dapper.osmond   IN    A      192.168.1.252

也可以写成如下的形式

wang.kevin.cn.            IN    A      192.168.0.251
dapper.kevin.cn.          IN    A      192.168.0.252
wang.osmond.kevin.cn.     IN    A      192.168.1.251
dapper.osmond.kevin.cn.   IN    A      192.168.1.252

对于有多个网络接口的计算机来说,可以使用多条 A RR 分别设置每个网络接口上的主机名与 IP 地址的映射。当然多个 IP 地址也可以关联同一个主机名。类似地,也可以使用多条 PTR RR 分别设置每个网络接口上的 IP 地址与主机名的映射。

PTR 资源记录
PTR RR 提供了 IP 地址到主机名的映射。其格式为:
IPAddress     [ttl]    IN    PTR    hostname

例如: 在 168.192.in-addr.arpa 区中,前面的 wang.kevin.cn. 和 dapper.kevin.cn. 所对应的 PTR 记录为:

251.0          IN    PTR      wang.kevin.cn.
252.0          IN    PTR      dapper.kevin.cn.

而在 0.168.192.in-addr.arpa 区中,前面的 wang.kevin.cn. 和 dapper.kevin.cn. 所对应的 PTR 记录为:

251          IN    PTR      wang.kevin.cn.
252          IN    PTR      dapper.kevin.cn.

在 1.168.192.in-addr.arpa 区中,前面的 wang.osmond.kevin.cn. 和 dapper.osmond.kevin.cn. 所对应的 PTR 记录为:

251          IN    PTR      wang.osmond.kevin.cn.
252          IN    PTR      dapper.osmond.kevin.cn.

在 PTR RR 中 hostname 应该使用全域名。例如 osmond.kevin.cn 域的主机 wang 应该写为 wang.osmond.kevin.cn. 。而 wang.osmond.kevin.cn 将被解析为 wang.osmond.kevin.cn.1.168.192.in-addr.arpa. 。
PTR RR 所提供的反向解析能够为任何对进入网络的请求进行认证的程序所使用,这些程序包括:sshd、tcpd、sendmail、syslogd 等。

MX 资源记录
MX RR 用于邮件系统实现邮件路由 。 其格式为:
zone    [ttl]   IN   MX   preference   host

其中 preference 是优先级字段,数值越小优先级越高。
示例如下:

kevin.cn.          IN    MX     5     wang.kevin.cn.
kevin.cn.          IN    MX     10    wang.kevin.cn.

CNAME 资源记录
CNAME RR 用于设置主机的别名。 其格式为:
nikename   [ttl]   IN   CNAME    hostname

示例如下:

wang            IN    A      192.168.0.251
www             IN    CNAME  wang
ftp             IN    CNAME  wang

文件内必须有规范名字的 A RR。

分析器指令
在区文件中还可以使用分析器指令,分析器指令可以为 RR 的输入提供方便。

$ORIGIN — 设置默认域(或初始域)
$TTL — 为没有定义精确的生存期的 RR 定义缺省的 TTL 值 

                                                                 遇到过一个DNS的forwarders转发设置的问题                                                         

IDC机房服务器上部署了内网DNS环境, 线上各服务器的/etc/resolv.conf文件里均配置了该DNS地址. 后来在其中过的一台服务器上去wget下载一个客户方的地址, 有时好有时坏, 由于该客户方的这个url里的域名采用了CDN加速, 所以在机房的这台服务器上"nslookup 该域名" 解析这个客户方的域名的ip是随时变的 (即解析到的都是CDN那边的地址池里的地址), 有时会解析不到这个域名的地址. 这是为什么呢?

发现是因为该机房DNS配置 (/etc/named/named.conf)里的forwarders转发到的NS服务器地址问题导致的. 因为之前配置的forwarders是:

      forwarders {
            223.5.5.5;
            223.6.6.6;
            8.8.8.8;
            8.8.4.4;
          };

即之前通过forwarders转发的NS地址是阿里云和谷歌的DNS地址.  后来又加上联通的DNS地址并放在了前面 (这几个DNS地址在forwarders转发时是轮询关系)就解决了上面问题:

      forwarders {
            114.114.114.114;
            202.106.0.20;
            223.5.5.5;
            223.6.6.6;
            8.8.8.8;
            8.8.4.4;
          };

如上添加后, 在机房的那台服务器上通过"nslookup 客户域名" 解析出来的ip地址相比于之前更多了.