分页: 1 / 1

[转贴]bind9配置精讲(二万字)

发表于 : 2009-10-30 8:55
bugle
原贴位置:http://shcore.com.cn/gugong/gugong/html/bind9.html,不过好像也是转贴的。全文超过二万字。

---------------------------------------------------------------------------------
架设 DNS

前面所介绍的服务器服务大多是用在内部网络环境中的,不过,以现代的情况和未来的趋势来看,每个网络或多或少都需要 Internet 联机以及向 Internet 提供服务。从这一章开始,我们将为大家陆续介绍一些在 Internet 环境中常用到的服务器之架设技巧。就算您目前还没真的需要架设 Internet 相关的服务器,但许多企业的 Intranet 环境中,也需要相类似的服务器来为企业内部网络提供服务。

前提条件

在众多 Internet 服务器当中,有一种服务是所有服务的基础,就是 DNS 服务。DNS 可以说是一个不容易弄清楚的概念,尤其是其运作原理。如果您看过“学习网络”中的“ DNS 协议”(我强烈建议您看看这篇文章!),相信应该有一定概念了,否则,您在如下的阅读中可能难以理解,也浪费您的时间。

无论如何,在您进一步阅读下面文章之前,请您先确定能正确回答如下的问题:


什么是 DNS 的授权模式?是怎样进行的?
请解释 zone 和 domain 的差别。
什么是 DNS 正解和反解?
什么是 DNS 的查询模式?查询过程是怎样进行的?
请解释 DNS cache 的作用和它对查询流程的影响。

如果您未能从上面的联结网页找到答案,那我再推荐您多看一篇文章:


http://turtle.ee.ncku.edu.tw/~tung/dns/dnsintro.html

忠告:请不必急着知道怎样设定 DNS,花点时间将 DNS 的原理弄明白非常重要,尤其是授权模式和查询模式的正确理解。在日后的 DNS 架设和管理中,是否能正确理解这些 DNS 原理,往往是成败的关键所在!

如果您在 NT 或 Win2K 下面设定过 DNS 服务器,相信您会觉得在 Linux 下面难多了。除了概念上要比较清楚外,另外对档案的关联也要有清晰的追踪能力,这对于进行 debug 尤为重要。因为在 Windows 系统上面,您的所有设定都透过图形界面进行,方便是方便,但也因为这个图形界面,限制了您的设定灵活性,同时也阻隔了您对 DNS 系统的深入了解。当您完成了这章的学习,而且成功在 Linux 架设出复杂的 DNS 环境之后,欢迎您再回到 Win2K 上尝试做同样的事情。或许,您就会认同我这里的观点了...

好了,闲话休提、言归正传,听百遍不如做一遍,那就让我们开始动手吧!



探索 NAMED

在 Linux 上面,提供 DNS 服务的套件是叫 bind, 但执行服务程序名称则是 named 。请您确定系统上装有 bind、bind-utils、以及 caching-nameserver 这几个套件,同时用 ntsysv 确定 named 被选择为开机服务。

首先,让我们设定一个最重要的 dns 设定档,它就是 /etc/named.conf 。我将我自己的设定档案列出来,然后逐部份进行解释:

// generated by named-bootconf.pl

options {
directory "/var/named";
/*
* If there is a firewall between you and nameservers you want
* to talk to, you might need to uncomment the query-source
* directive below. Previous versions of BIND always asked
* questions using port 53, but BIND 8.1 uses an unprivileged
* port by default.
*/
// query-source address * port 53;
};



先让我们了解这个档案上面用来做批注的符号是“ // ”,而不是一般 shell script 的“#”;另外,“ /* ”与“ */ ”之间则批注一整段文字。同时,每一个完整的设定都以“ ;”结尾,请不要少了它!(初学者经常会犯这个错误)

上面的部份是在这个档案开头的 options 设定,首先用 directory 指定了 named 的资源记录( RR - Resource Record )档案目录所在位置为:“/var/named”;也就是说,它会到这个目录下面寻找 DNS 记录档案。所以,我们在这个档案后面部份所指定的档案,就无需使用绝对路径了,但它们一定要放在这个目录下面。

接下来,有一段文字,如果您仔细阅读一下,它大致是说:如果您要设定的 DNS 服务器和 client 之间是隔着火墙的话,要将“// query-source address * port 53;”前面的批注符号“ // ”拿掉(当然,您也必须要设定好您的火墙啦)。不过,这只对早期的版本有影响,而在 bind 8.1 之后则无需担心这个设定。

接下来再让我们看下一段句子:

//
// a caching only nameserver config
//
zone "." IN {
type hint;
file "named.ca";
};



透过这几行,我们为 named 定义了 DNS 系统中的根区域“ . ”(root zone) 的设定,同时它是一个 internet ( IN ) 的区域类别( class )。这里还指定了root zone 的服务器种类( type ) 为“hint”(也只有这个 zone 会使用这样的种类)。最后,用 file 指定这个区域记录文件为:“named.ca”,也就是“/var/named/named.ca”档案。虽然 named.ca 这个档案中的‘ca’是 cache 的意思;但如果您了解 DNS 的运作,就应该知道这个暂存盘的作用,同时,为什么我们会把 root zone 放在这里。(嗯?想想看?尤其是查询非本机区域的时候?)

在 root zone 后面,您应该还会看到如下这两段:

zone "localhost" IN {
type master;
file "localhost.zone";
allow-update { none; };
};

zone "0.0.127.in-addr.arpa" IN {
type master;
file "named.local";
allow-update { none; };



这里是定义出关于本机名称的 DNS 解释:第一个 zone 是 localhost 的正解 zone,其服务器种类是 master,记录文件名称是 localhost.zone (在 /var/named 目录下面),但这个 zone 不允许客户主机(或服务器)自行更新 DNS 的记录(当然,client 主机必须能支持 DNS submit 功能才行)。

而第二个 zone 则是本机区域的反解 zone ,不过,这部份的解释我想留到后面的真实例子中再作说明,请您留意就是了。

上面的句子,当您安装好 caching-nameserver 套件之后就被建立起来的,相信您不用劳什么心力。在档案最后,您或许还看到下面这段设定:

key "key" {
algorithm hmac-md5;
secret "coqJswFdBMdNAItnLOpkmGgmJtccFsoNZZciWqxlGZBMUTOUxb0geYMFRyTT";
};



这是 bind 9.x 版本的新功能,用来进行区域转移或 DNS 更新所用的加密处理。这个我们暂时不必理会,除非您有兴趣进行这个研究。

现在,我们暂时不要修改 named.conf 设定档,请退出它,然后转到 /var/named 目录,看看里面有些什么东东?最起码,您会看到如下三个档案:


named.ca
localhost.zone
named.local

不知道您是否有灵感了?没错:刚才在 named.conf 里面,每一个 zone 所指定的 file 都出现在这里!先让我们看看 root zone 的档案内容吧:

; This file holds the inFORMation on root name servers needed to
; initialize cache of Internet domain name servers
; (e.g. reference this file in the "cache . "
; configuration file of BIND domain name servers).
;
; This file is made available by InterNIC registration services
; under anonymous FTP as
; file /domain/named.root
; on server FTP.RS.INTERNIC.NET
; -OR- under Gopher at RS.INTERNIC.NET
; under menu InterNIC Registration Services (NSI)
; submenu InterNIC Registration Archives
; file named.root
;
; last update: Aug 22, 1997
; related version of root zone: 1997082200
;
;
; FORMerly NS.INTERNIC.NET
;
. 3600000 IN NS A.ROOT-SERVERS.NET.
A.ROOT-SERVERS.NET. 3600000 A 198.41.0.4
;
; FORMerly NS1.ISI.EDU
;
. 3600000 NS B.ROOT-SERVERS.NET.
B.ROOT-SERVERS.NET. 3600000 A 128.9.0.107
;
; FORMerly C.PSI.NET
;
. 3600000 NS C.ROOT-SERVERS.NET.
C.ROOT-SERVERS.NET. 3600000 A 192.33.4.12
;
; FORMerly TERP.UMD.EDU
;
. 3600000 NS D.ROOT-SERVERS.NET.
D.ROOT-SERVERS.NET. 3600000 A 128.8.10.90
;
; FORMerly NS.NASA.GOV
;
. 3600000 NS E.ROOT-SERVERS.NET.
E.ROOT-SERVERS.NET. 3600000 A 192.203.230.10
;
; FORMerly NS.ISC.ORG
;
. 3600000 NS F.ROOT-SERVERS.NET.
F.ROOT-SERVERS.NET. 3600000 A 192.5.5.241
;
; FORMerly NS.NIC.DDN.MIL
;
. 3600000 NS G.ROOT-SERVERS.NET.
G.ROOT-SERVERS.NET. 3600000 A 192.112.36.4
;
; FORMerly AOS.ARL.ARMY.MIL
;
. 3600000 NS H.ROOT-SERVERS.NET.
H.ROOT-SERVERS.NET. 3600000 A 128.63.2.53
;
; FORMerly NIC.NORDU.NET
;
. 3600000 NS I.ROOT-SERVERS.NET.
I.ROOT-SERVERS.NET. 3600000 A 192.36.148.17
;
; temporarily housed at NSI (InterNIC)
;
. 3600000 NS J.ROOT-SERVERS.NET.
J.ROOT-SERVERS.NET. 3600000 A 198.41.0.10
;
; housed in LINX, operated by RIPE NCC
;
. 3600000 NS K.ROOT-SERVERS.NET.
K.ROOT-SERVERS.NET. 3600000 A 193.0.14.129
;
; temporarily housed at ISI (IANA)
;
. 3600000 NS L.ROOT-SERVERS.NET.
L.ROOT-SERVERS.NET. 3600000 A 198.32.64.12
;
; housed in Japan, operated by WIDE
;
. 3600000 NS M.ROOT-SERVERS.NET.
M.ROOT-SERVERS.NET. 3600000 A 202.12.27.33
; End of File



在 /var/named 中的 RR 记录文件里面的批注符号,和 /etc/named.conf 的批注符号不一样哦:在 named.conf 中是用双斜线“ // ”;而在这里则使用 “ ;”符号。无论如何,您都不能用 “ # ”来做批注符号就是了。(好混乱哦~~~ 这就是计算机!^_^ )

在上面这个 named.ca 档案里面,您如果将所有的批注行拿掉,您会发现一共有 13 行是以‘ . ’开头的,那就是所谓的 root zone 了!然后,第二栏都是‘ 3600000 ’,这是 TTL (Time To Live) 设定,也就是在 cache 中保留的时间,以秒为单位(所以这里是 100 小时)。其后的‘ NS ’是“Name Server”的意思,是 DNS 记录名称之一,也就是负责这个记录的 name server 是哪一台主机(这里一共由 13 台主机共同负责 root zone 的 NS 服务)。

虽然我们这里用 NS 指定了 name server 的主机名称,但对计算机系统来说,这些名称必须能解释为 IP 地址才有用(呵~~ 这个正是 DNS 系统的功能),所以,这里分别用 13 个‘ A ’记录,也就是 Address 的意思,解释 [A-M].ROOT-SERVER.NET. 这些主机各自的 IP 地址所在。

如果您了解 DNS 的查询模式,您会知道 DNS 服务器在查询非自己管辖的 zone 的时候,首先会向 root 查询下一级的 zone 在哪里,然后逐级查询下去。但问题是:当 named 刚启动的时候,在 cache 里面一片空白,它怎么知道 root zone 的 servers 在哪里呢?这不是一个矛盾吗?所以,就必须靠这个档案告诉 named 关于 root zone 的 servers 有哪些?以及在哪里? --- 明白了吗?

因为这个文件是以静态的方式维护的,很难保证这个档的内容永远都正确,如果 root zone 的记录发生改变了怎么办(虽然这机会不大)?或许,您已经在档案的开头批注那里得知,您可以在任何时候透过 ftp 或 gopher 取得这个档案的最新版本。如果您还没读过那些批注,那就请带着字典读一下吧。如果您真的有需要更新这个 named.ca 档,那可以按如下步骤进行:

ftp FTP.RS.INTERNIC.NET
anonymous
your_account@your.mail.server
cd domain
get named.root
bye
cp /var/named/named.ca /var/named/named.ca.bak
cat named.root > /var/named/named.ca


除了刚才的 named.ca 之外,第二个 zone 的记录文件是 localhost.zone ,从 named.conf 中您应该知道它是 zone "localhost" 的记录文件,它的内容如下:

$TTL 86400
$ORIGIN localhost.
@1D IN SOA @ root (
42 ; serial (d. adams)
3H ; refresh
15M ; retry
1W ; expiry
1D ) ; minimum

1D IN NS @
1D IN A 127.0.0.1



内容很简单,但您是否真的了解每一行的设定意思呢?如果不清楚或不确定,那就让我们一起探讨探讨吧。

首先,第一行是一个 TTL 设定,目前是定义出这个记录文件里面的各项记录的预设 TTL 值为 86400 秒(刚好是一天)。您的记录文件或许没有这行,事实上没什么关系,您可以自己补上,否则,在启动 named 的时候会碰到一些警告,无伤大雅的;但如果您的确在意那些警告,那就加上这行。您要知道,在记录文件中宣告的所有资源记录(RR - Resource Record),都一定有一个 TTL 设定,如果没有,则使用这里预设的值。

第二行是一个 ORIGIN 设定,说明下面的记录源出何处(这里是源出 localhost. 的记录)。请您加倍留意最后的一个小数点“ .”,少了它或多了它,记录名称完全不一样!在 DNS 记录中,我们称这样以小数点结尾的名称为“ 全域名称 ”即 FQDN ( Fully Qualified Domain Name ) 。如果缺少了这个点会怎样呢?就会将所属的 ORIGIN ( @ ) 附加在记录名称后面;而这 ORIGIN 就是上一个 $ORIGIN 宣告之后的名称,如果在前面找不到 $ORIGIN 宣告,那就以 /etc/named.conf 中定义的 zone 名称为基准。以目前的例子来说,如果没有这个小数点的话,“localhost”会变成“localhost.localhost”;但如果有小数点的话 “localhost.”就只能是“localhost.”。所以,这个小点“.”非常重要,在以后设定中一定要非常留神!!(这也初学者最常犯的错误之一)

然后,第三行,是一个 SOA 记录的设定,在这里我们看到一个特殊字符“ @ ”,它就是 ORIGIN 的意思,也就是刚才所定义的 $ORIGIN localhost. 内容,您可以写成 localhost. 也可以用 @ 来代替。假如这个档前面没有定义 $ORIGIN 的话,那这个 @ 的值就以 named.conf 里的 zone 为准。既然这样,当然是使用“@”啦,尤其对于像我这样的懒惰鬼来说,巴不得少打一串字,同时还能避免因打字不准所造成的失误,何乐不为?

在 @ 之后,是 TTL 的设定,这里是 1D,也就是一天的意思,如果您喜欢,可以用 86400 (秒) 来设定,如果这里的 TTL 没有设定,则参考前面的 $TTL 值,如果前面没有定义 $TTL,那就参考其后介绍的 minium ttl 设定。


Tips:事实上,您可以为每一个 RR 记录设定其自己的 TTL ,只要将数字写在第二个字段,也就是‘IN’前面就可以了。

在 TTL 之后是一个 IN,定义出目前的记录类型是属于 internet class 的 (奇怪,目前的 DNS 还有其它 class 吗?)。

在 IN 之后就是这行 RR 的记录类别名称,这里是 SOA ,也就是“Start Of Authority”的意思,表示目前区域的授权记录开始。每一个记录文件只能有一个 SOA ,不得重复,而且必须是所负责的 zone 中第一个“记录”。

紧接 SOA 后面,指定了这个区域的授权主机和管理者的信箱,这里分别是“ @ ”和“ root ”,也就是 localhost. 主机和 root 信箱。这里要注意的是:SOA 的主机名称必须能够在 DNS 系统中找到一个 A 记录 (以后会提到);另外,我们平时使用的信箱通常是“user@host”这样的格式,但因为“@”在 DNS 记录中是个保留字符(刚才已经提过),所以在 SOA 中就用“.”来代替了“ @ ”。目前这个信箱是 root (并没有主机地址),也就是本机,您可以写成 “root.localhost.”但不能写成“root@localhost.”。

接下来的 SOA 设定,是被括在“( )”之间的 5 组数字,主要作为和 slave 服务器同步 DNS 数据所使用的数据:


Serial:其格式通常会是“年月日+修改次序”(但也不一定如此,您自己能够记得就行)。当 slave 要进行数据同步的时候,会比较这个号码。如果发现在这里的号码比它那边的数值“大”,就进行更新,否则忽略。不过设 serial 有一个地方您要留意:不能超过 10 位数字!
Refresh:这里是是告诉 slave 要隔多久要进行数据同步(是否同步要看 Serial 的比较结果)。
Retry:如果 slave 在进行更新失败后,要隔多久再进行重试。
Expire:这是记录逾期时间:当 slave 一直未能成功与 master 取得联络,那到这里就放弃 retry,同时这里的数据也将标识为过期( expired )。
Minimum:这是最小预设 TTL 值,如果您在前面没有用“$TTL”来定义,就会以此值为准。

以上的数字都是以秒为单位,但您也可以用 H(小时)、D(天)、W(星期)来做单位,如:3H 和 259200 是一样的。但要值得一提的是:我在 RH6.2 版本中曾测试过使用 netconf 这工具来设定 DNS ,发现只能使用“秒”来设定。否则 netconf 会自动的把英文字母删除掉,那就不是我所预期的设定值了。无论您用什么单位来设定,都要遵守下面的规则:

expire >= refresh + retry
expire >= 10 * retry


Tips:请注意:SOA 记录中这对 “ ( ) ”符号之第一个 “ (”括号一定要和 SOA 写在同一行,而不能用 Enter 断行到下一行去(有时候您在书本的范例中看到这个符号排在下一行去了,那是因为版面的关系而已),而且其左边最好有一个空格键或 tab 建。而最后一个 “ )”括号也不能写在批注符号 “ ;”的右边。

设定 DNS 的 RR 记录文件,其格式要求非常严格,我们丝毫不能掉以轻心。比方说:如果句子不是以空格键、Tab 键、 或批注符号 ( ; )开头,也不在 SOA 的 “ ( ) ”之内, 则表示要定义一个“新记录项 (Entry) ”;如果句子是以空格键或 tab 键开始的话,其设定被视为上一个“记录项”的内容。所以,如果您要为“同一个记录项”定义多个记录设定,而不想重复打字,您倒可以偷懒:在接着它的后面几行用空白或 Tab 来缩排就可以了。所以,最后这两行还是关于 localhost. 的设定,因为上一个“数据项”为 “ @ ”,也就是 localhost. 。当然,您如不喜欢,这两行句子也可以这样写:

;; 修改前:
1D IN NS @
1D IN A 127.0.0.1

;; 修改后:
@1D IN NS @
@1D IN A 127.0.0.1

;; 或:
localhost.1D IN NS localhost.
localhost.1D IN A 127.0.0.1



这两行的意思是说:负责 localhost. 这个记录的 name server ( NS ) 是 localhost. 这台机器;而 localhost. 的 IP Address ( A ) 是 127.0.0.1 。DNS 里面的 A 记录应该是最常见的记录类型之一,如果在 IPv6 版本中,地址记录名称则改为 AAAA 。


Tips:关于更多的记录名称,请参阅“学习网络”中的“DNS 协议”。

最后,让我们检查剩下的 named.local 档案吧。如果您还没忘记 /etc/named.conf 的内容的话,应知道这个档案是 zone "0.0.127.in-addr.arpa" 的‘反解’记录文件,它的内容也很简单:

$TTL 86400
@ IN SOA localhost. root.localhost. (
1997022700 ; Serial
28800 ; Refresh
14400 ; Retry
3600000 ; Expire
86400 ) ; Minimum
IN NS localhost.

1 IN PTR localhost.



前面的部份应该不用多解释了(如果您还不清楚,那就必须重读前面的文章)。最后一行我们看到一个“ PTR ”记录,它是“Pointer”的意思。 PTR 通常用于反记录当中,将 IP 指向主机名称(刚好和 A 记录相反)。您或许还不是很清楚这个句子为什么是这样设定的吧?或许您会这样问:您不是说 PTR 是从 IP 反查询主机名称的吗?为什么这里是 1 而不是 127.0.0.1 ?

哦,如果您有这样的问题,那证明您对 DNS 的查询模式还不是了解得很透彻,不过也不用紧张,在后面的实作例子中,您将获得更进一步的感性认识。这里,我暂时简单解释上面这行就是了:

我们知道 127.0.0.1 所对应的主机名称就是 localhost ,因为这里是反向查询,所以 IP 顺序是掉过来写的,于是这个反查询 IP 就是:“ 1.0.0.127.in-addr.arpa. ”,由于我们这里的 ORIGIN ( @ ) 是“ 0.0.127.in-addr.arpa." ”,因为在记录文件中,如果名称不带小数点,则被补上 $ORIGIN 或 zone 的名称,所以这个 “ 1 ”就成了 1.0.0.127.in-addr.arpa. ”。同样道理,后面的“ localhost. ”如果漏了最后的小点的话,则会成为“ localhost.0.0.127.in-addr.arpa. ”,这显然是不对的。假如您喜欢,可以将这行句子修改成为下面的样子:

;;修改前:
1 IN PTR localhost.

;;修改后:
1.0.0.127.in-addr.arpa. IN PTR localhost.



嗯~~ DNS 的设定看起来真的蛮伤脑筋的,或许您到这里已经被搞得乱七八糟了。假如真的如此,我建议您先休息一下,然后回来重读上面的内容,直到您能理解之后,才继续下面的。否则,越往后,您的问题越像滚雪球那样越来越大,这更浪费时间啦~~~ Okay? Take it easy ...

前面所看到的设定,事实上已经足够让您的 DNS 主机跑起来了!因为它能够透过 root 查询其它 DNS 的缘故,您无须在再加设任何设定,您就可以利用这台主机为大家提供 Internet 的 DNS 查询服务。只是,这样的 DNS 主机,我们称之为 cache only name server 而已。如果您了解 DNS 的查询流程,您应该知道 DNS 的 cache 作用和它的效益。所以,就算您不打算设定自己的 domain name 服务 ,我也建议您至少可以将 cache only NS 跑起来。

设定 NAMED

当您对 /etc/named.conf 档案和 /var/named 目录的设定有初步了解之后,下面,让我们用一个实际例子来看看如何设定自己的 domain name 服务吧。我个人的习惯是先将网域和主机的数据整理出来,并列成一个表格:

Domain 名称 IP 地址
rh71.siyongc.domain 192.168.100.23
acer.siyongc.domain 192.168.100.20
mdk.siyongc.domain 192.168.100.24
emilie.siyongc.domain 192.168.100.11
rh71.dmz.domain 10.0.1.131
lp64.dmz.domain 10.0.1.130


当所有的主机名称和 IP 整理出来之后,再看看我们这里需要设定哪些 domain ? 从上面的数据中,我们不难发现有两个正解 zone 和两个反解 zone 需要设定,分别是:

区域名称 记录项名称
siyongc.domain emilie、acer、rh71、mdk
dmz.domain lp64、rh71
100.168.192.in-addr.arpa 11、20、23、24
1.0.10.in-addr.arpa 130、131


因为这些 IP 和 domain 都在内部网络使用,所以我们省却了注册这关,同时也不必担心授权的问题。但这些信息也只能在内部网络使用,无论如何是不能设定在对外的 DNS 上面的 (为什么?除了安全的考虑之外,private IP 的使用本来就有这样的规定,就算您真的对外散布这些 DNS 信息,在 IP 的路由上还是有问题,所以,内部的信息,只能内部使用)。

一般来说,我会先设定“反查询区域(revers zone)”,当然,这是个人习惯而已。所以,我首先在 /etc/named.conf 上面补上两个反解 zone 的设定:


zone "100.168.192.in-addr.arpa" IN {// 定义反解区域名称
type master;// 定义服务器类型
file "192.168.100.rev";// 指定记录文件名称
};// 结束区域设定

zone "1.0.10.in-addr.arpa" IN {
type master;
file "10.0.1.rev";
};



注意哦:如果您要设定外部 DNS 的反解,那就先获得 ISP 的授权才能自己设定;否则反解部份就不用自己担心了,但一定要请 ISP 帮忙。


Tips:假如您是 hinet 的固定制 ADSL 用户,可以到 hinet 的网站填写表格,请他们帮忙设定反解:


http://hidomain.hinet.net/rever.html

其它 ISP 的用户,请自行接洽 ISP 的客服部门。无论如何,如果没有取得授权,那就不要自己设!


这里,我们再一次碰到反解区域的识别标志:“ .in-addr.arpa ”,同时,我们解释一下上次关于本机反解还没说明的地方:如果您了解 DNS 的授权和查询过程(这章一开始的时候,我就已要求您一定要学习的),您会知道反解查询是先从 root 开始(正解也是一样),然后到 arpa 、到 in-addr 、到第一组 IP 、到第二组 IP 、...... 这样查询下来的。所以,在设定反区域的时候,您一定要将您的 net ID 部份反过来写,例如:我的网络为 192.168.100.0/24,它的反查询区域名则是:“100.168.192.in-addr.arpa”;假如我将 netmask 改为 16 bit ,即变成 192.168.0.0/16,它的反解区域名就会变成:“168.192.in-addr.arpa”。如果您还搞不懂如何区分 Net ID 和 Host ID,请立即去看一看“学习网络”中的“IP 基础”。

同时,我将这些 zone 都设定为“主 DNS 服务器”(即:master,也有人称之为 primary dns )。

在每个 zone 的最后部份,我分别指定了它们各自的记录文件名称。它们都存放在 /var/named 这个目录下面(也就是前面 options 指定的 directory 啦)。档案的名称随您喜欢,不致做成混乱则可。

完成上面的设定之后,我们就可以到 /var/named 目录去建立相应的记录档案了。说实在,在 named.conf 里面如何定义文件名称没一定的标准,只要您能正确指定哪个记录文件给哪个 zone 使用,而且文件名称能够一致就行。首先,根据第一个 zone 的 file 设定,我要建立一个 /var/named/192.168.100.rev 档案,其内容如下:

$TTL 86400
@ IN SOA rh71.siyongc.domain. root.rh71.siyongc.domain. (
2001111601 ; Serial
28800 ; Refresh
14400 ; Retry
3600000 ; Expire
86400 ) ; Minimum
@ IN NS rh71.siyongc.domain.
@ IN NS lp64.dmz.domain.

11 IN PTR emilie.siyongc.domain.
20 IN PTR acer.siyongc.domain.
23 IN PTR rh71.siyongc.domain.
24 IN PTR mdk.siyongc.domain.



而另外一个反解设定档是 /var/named/10.0.1.rev ,我们依样画葫芦就行了:

$TTL 86400
@ IN SOA rh71.siyongc.domain. root.rh71.siyongc.domain. (
2001111601 ; Serial
28800 ; Refresh
14400 ; Retry
3600000 ; Expire
86400 ) ; Minimum
@ IN NS rh71.siyongc.domain.
@ IN NS lp64.dmz.domain.

130 IN PTR lp64.dmz.domain.
131 IN PTR rh71.dmz.domain.



就这样,反解 DNS 就设定完成了!是否很简单呢?如果您回答“ Yes ”的话,那就让我们继续正解区域的设定吧。同样的,先在 /etc/named.conf 里面加上两个 zone:

zone "siyongc.domain" IN {
type master;
file "siyongc.domain";
};

zone "dmz.domain" IN {
type master;
file "dmz.domain";
};



完成后,再建立 /var/named/siyongc.domain 这个档案:

$TTL 86400
$ORIGIN siyongc.domain.
@ IN SOA rh71.siyongc.domain. root.rh71.siyongc.domain. (
2001111601 28800 14400 3600000 86400 )
IN NS rh71.siyongc.domain.
IN NS lp64.dmz.domain.
IN MX 10 rh71.siyongc.domain.
IN MX 20 lp64.dmz.domain.

;; -- default address
@ IN A 192.168.100.23

;; -- linux servers --
rh71 IN A 192.168.100.23
IN MX 0 rh71.siyongc.domain.
IN MX 10 lp64.dmz.domain.
IN HINFO "Petium II 266""Redhat 7.1"
IN TXT "The internet gateway."

mdk IN A 192.168.100.24
IN MX 0 mdk.siyongc.domain.
IN MX 10 rh71.siyongc.domain.
IN HINFO "Petium II 266 dell""Mandrak 8.0"

;; -- Windows desktops --
acer IN A 192.168.100.20
IN MX 0 mdk.siyongc.domain.
IN HINFO "Petium III 800 acer""Windows ME"

emilie IN A 192.168.100.11
IN MX 0 mdk.siyongc.domain.
IN HINFO "Petium II 300""Windows 98"

;; -- cnames --
gw IN CNAME rh71
www IN CNAME rh71
ftp IN CNAME rh71
mail IN CNAME rh71



这里,我们在正解记录文件里面看到几个新的记录类别,或许需要进一步讲解一下的:

因为我这个区域的记录分别由两台主机负责,所以我这里指定了两个 NS 记录。这里,如果您确定上一个 ORIGIN 是正确的话,那也可以偷懒:正如我上面解释过,如果名称后面不是以“.”结尾的话,它所属的 ORIGIN ( @ ) 就会自动的加在该记录名称后面;所以,您可以只写“ rh71 ”而不带小数点结尾,就会变成“rh71.siyongc.domain.”了,这个名称实际就是我所要的。不过,我建议您在设定 NS 的时候还是尽量使用 FQDN 为好。

接下来的 ‘ MX ’ 记录恐怕要花些时间解析:


MX 记录

MX 是‘Mail eXchange’的意思,它指定了负责该记录项(可以为 domain 也可以是 host )的邮件服务器名称(最好使用 FQDN ),而且该名称必须是一个 A 记录(不建议使用 CNAME )。

在邮件系统中,只要邮件服务器双方都知道对方的 IP 就可以进行邮件交换了。我们用 /etc/hosts 也可以做到名称查询的目的,但正如我们可以想象的:ineternet 有那么多邮件服务器,我们不可能一一为它们建立好 IP 对应。就算,我们可以这样做,如果对方要更换邮件服务器呢?要维护这样一个对应殊非易事。既然,我们可以用 DNS 来查询主机和 IP,为什么不使用这么便利的系统呢?这也是 DNS 系统的应用原因啊~~~ 但问题是,各区域的邮件服务器名称都不一样,我们不可能知道对方的邮件服务器主机名称是什么?就算知道,如果对方以后更换名称呢?

您看,即使我们使用了 DNS 系统来进行邮件路由,也不是这么简单的事情。但是,使用 MX 记录就大大发挥了 DNS 系统的功能了:我们只要为每一个区域建立起 MX 记录,利用 DNS 查询得到的邮件服务器名称(邮件路由查询中,DNS 只是其中一种方法),这样,当邮件服务器要和对方的区域进行邮件传递的时候,就可以通过 MX 记录得到对方的邮件服务器名称,而不需预先知道要和哪台邮件主机沟通。在日后,就算对方更换名称,将 DNS 记录改改就可以,完全无需知会其它邮件主机;而外面的邮件服务器也根本无需认知到这个改变。

这样的设计,无疑是非常灵活便利的!另外,使用 MX 还有一个功能:您可以用多个 MX 同时指定好几台邮件服务器名称,从而提供备援或平行处理服务。在我这个例子中,我就分别为‘siyongc.domain’这个区域指定了两个 MX 记录:‘rh71.siyongc.domain.’和‘lp64.dmz.domain.’。但您有没有发现它们前面都有一个数字呢?这数字有什么作用啊?

问得好!当外面的邮件服务器通过 DNS 查询到我们的邮件服务器,如果发现超过一台主机负责邮件交换的话,数值越低的就越先被查询。但有时候该主机没有响应呢?那么就由下一个数值的主机负责了。这样有一个好处就是:就算第一台邮件服务器出现故障,也不至于导致邮件交换功能瘫痪掉。我们通常会将各自的 MX 主机尽量分布在不同的位置上(例如别的城市或国家的分公司主机),假如万一发生专线、甚至 ISP 的问题,我们还能将邮件转往下一台 MX 主机。然而,在设计上,由于账号和 client 端的设定因素,我们的邮件并非真的完全转到下一个 MX 主机接收,而是先将邮件暂时队列( queue ) 在那台机器上,当原来的 MX 主机恢复联机之后,邮件会自动的从队列主机那边送回来,这样就能避免邮件丢失或被退信。


Tips:虽然,我们通常喜欢用‘10’、‘20’、‘30’.... 这样的偏好值( preference ) 来分配 MX 记录,但只要您喜欢,用‘1’、‘2’、‘3’... 这样的顺序一样可以。不过,我建议您还是使用惯例啦。

现在很多大型邮件系统,都可以同时使用多台邮件主机来提供邮件交换服务,这时候您可以将 MX 的 preference 设为相同,然后利用 NIS 和 NFS 服务,将邮件同步到相同的账号去。您已经在前面的章节里面学会了 NIS 和 NFS,等日后学习邮件主机架设的时候,不妨玩玩看!


或许,您还发现我这里为所有主机指定了 MX 记录,有些直接指向自己(如 rh71、mdk 等),而有些则指向别的机器(如 lp64、acer 等)。在 Linux 机器上面,各主机本身就具备邮件交换功能(除非您将之移除了),而 Windows 则除非额外加装,否则本身是没有邮件交换功能的。这里的设定是,从外面通过 DNS 查询而寄往那些主机的邮件,都会转到 MX 上面指定的邮件服务器。这在实际的网络环境中很常见,尤其您接触过“ mail hub ”这个概念。无论如何,我建议您应该帮负责 domain 的邮件服务器本身设定一个偏好值最低的 MX 记录指向自己(但这不是硬性必须如此的)。


Tips:事实上,我当初对 MX 的理解一直存在着错误,直到有一次在新闻组上和大家讨论,才纠正过来。如果您对这个故事感兴趣的话,或是想更进一步了解 MX 的实际运作原理,请参考 << Sendmail 与 MX >> 一文。

在过去,有些人并不知道如何正确的运用 MX 记录,但相对的,他们会为 domain 名称本身设定一个 A 记录 (@ IN A 192.168.100.23 )。这样的做法虽然不是正统的,但也行之有年了。而且,在许多网站的 URL 上,这样的设定,也能让您少输入“ www. ”这四个键~~~


另外,在这个档里面,您或许还发现‘ TXT ’这样的记录类别,它是‘Text InFORMation’的意思,它实际上不牵涉任何设定,只记录一些环境说明而已;这和‘ HINFO(Host InFORMation) ’差不多,但 HINFO 一定要有两项记录(分别用引号分开),其中第一项是关于 CPU 的讯息,第二项则是操作系统。然而,TXT 和 HINFO 这些信息仅能在一个信任的环境中提供,如果您架设的 DNS 是对外提供服务的,那么,就不要设定这些信息了。要不然,入侵者可非常感谢您哦,因为您帮他们省却了很多主机系统的探测手续~~~ 所以,这里仅做范例,供您参考而已。

而最后您所看到的‘CNAME’记录又是怎样的呢?CNAME 也是一个常见的记录类别,它是一个别名记录( Canonical Name )。当 DNS 系统在查询 CNAME 左面的名称的时候,都会转向 CNAME 右面的名称再进行查询,一直追踪到最后的 PTR 或 A 名称,成功查询后才会做出响应,否则失败。例如,在正解查询中,一个 IP 通常(当然也有例外),只会对应一个 A 记录,但我们可以使用 CNAME 在 A 名称之上赋予该 IP 更多的名称。也就是说:所有关于‘www.siyongc.domain’、‘ftp.siyongc.domain’、 ‘mail.siyongc.domain’这些名称的查询,实际上都会再查询一次‘rh71.siyongc.domain.’这个记录,直到找到它的 IP 地址为止。有些朋友或许会设定多层的 CNAME 查询,例如:


C CNAME B
B CNAME A

这样的话,会一层一层的逐级 CNAME 下去... 但是,这很浪费 DNS 资源!因为每一个 CNAME 都一定会产生另外一个查询动作,如果层级越多,那就产生越多的重复查询。所以,精明的 DNS 管理员,都会尽量的减少查询次数的发生,他会将 CNAME 变成这样子:


C CNAME A
B CNAME A

这样就用心多了!

基本上,我们在正解设定上所使用到的记录大概就前面所看到的。哦,对了~~ 还有另外一个 /var/named/dmz.domain 档案也不要忘记了:

$TTL 86400
$ORIGIN dmz.domain.
@ IN SOA rh71.siyongc.domain. root.rh71.siyongc.domain. (
2001111601 28800 14400 3600000 86400 )
IN NS rh71.siyongc.domain.
IN NS lp64.dmz.domain.
IN MX 10 rh71.dmz.domain.

;; -- linux servers --
rh71 IN A 10.0.1.131
IN MX 0 rh71.dmz.domain.
IN HINFO "Petium II 266""Redhat 7.1"
IN TXT "The internet gateway."

lp64 IN A 10.0.1.130
IN MX 0 rh71.dmz.domain.
IN HINFO "Pentium 90""Linpus 6.4"

;; -- cnames --
gw IN CNAME lp64
www IN CNAME lp64
ftp IN CNAME lp64
mail IN CNAME lp64



您看!就这样,我们的 DNS 就已经设定好了,包括反解和正解哦~~~

重新启动 named

当您以为所有设定档都设定好之后,最想做的事情莫过于要测试一下啦。但在测试之前,我们还要重新启动 named ,否则,您查询出来的还是旧数据。聪明的您或许已经知道使用如下命令来重新启动DNS 服务了吧:

service named restart


然而,作为一个有经验的 DNS 管理员,在重新启动 named 服务之后,他一定会检查一个档案,就是 /var/log/messages 。因为,许多时候,当您执行 service named restart 之后您看到的都是绿色的 OK ,但事实上是否真的 OK 呢?谁也不敢保证,除非您在 log 档中没发现错误信息。所以,我也强烈建议您每次重新启动 named 之后,一定一定要做如下动作:

vi /var/log/messages


然后按“G”键(大写)跳到档案末尾部份(事实上,您也可以用 tail 命令)。您或许会看到如下这样的记录:

Nov 16 14:54:10 rh71 named[2211]: starting BIND 9.1.0 -u named
Nov 16 14:54:10 rh71 named[2211]: using 1 CPU
Nov 16 14:54:10 rh71 named: named startup succeeded
Nov 16 14:54:10 rh71 named[2215]: loading configuration from '/etc/named.conf'
Nov 16 14:54:10 rh71 named[2215]: the default for the 'auth-nxdomain' option is now 'no'
Nov 16 14:54:10 rh71 named[2215]: no IPv6 interfaces found
Nov 16 14:54:10 rh71 named[2215]: listening on IPv4 interface lo, 127.0.0.1#53
Nov 16 14:54:10 rh71 named[2215]: listening on IPv4 interface eth0, 192.168.100.23#53
Nov 16 14:54:10 rh71 named[2215]: listening on IPv4 interface eth1, 10.0.1.1#53
Nov 16 14:54:10 rh71 named[2215]: listening on IPv4 interface eth2, 10.0.1.131#53
Nov 16 14:54:10 rh71 named[2215]: listening on IPv4 interface vmnet1, 172.16.233.1#53
Nov 16 14:54:10 rh71 named[2215]: listening on IPv4 interface vmnet8, 192.168.183.1#53
Nov 16 14:54:10 rh71 named[2215]: listening on IPv4 interface ppp0, 211.74.244.213#53
Nov 16 14:54:10 rh71 named[2215]: running



上面虽然有 'auth-nxdomain' 和 IPV6 的提示,但那是正常的(除非您有设定相关的功能)。如果没有其它错误信息的话,那真要恭喜您了!

但有时候您或许会看到有其它错误信息的,例如:

Nov 16 15:01:49 rh71 named[2287]: loading configuration from '/etc/named.conf'
Nov 16 15:01:49 rh71 named[2287]: /etc/named.conf:41: parse error near zone
Nov 16 15:01:49 rh71 named[2287]: loading configuration: failure
Nov 16 15:01:49 rh71 named[2287]: exiting (due to fatal error)



这个错误信息明显指出了是 /etc/named.conf 的问题,而且很可能在 41 行附近。根据我个人的经验,这通常是您漏了 “ ;”符号的原因而已。

如果您碰到如下信息,那是没有为所有 RR 记录项设定 TTL 而已,您可以为每一个记录项补上 TTL (在 IN 前面),也可以在记录文件的前面用 $TTL 来设定:

Nov 16 15:04:47 rh71 named[2395]: master.c:1172: unexpected error:
Nov 16 15:04:47 rh71 named[2395]: dns_master_load: siyongc:3: no TTL specified.
THIS ZONE WILL NO LONGER WORK IN FUTURE VERSIONS. Add a TTL.
Nov 16 15:04:47 rh71 named[2395]: dns_master_load: siyongc:5: using
RFC 1035 TTL semantics



如果您碰到下面这样的信息,那多是因为您打字错误的关系,输入了 named 不认识的记录类别名称(例如漏了记录名称或打错了):

Nov 16 15:07:44 rh71 named[2422]: dns_master_load: siyongc:2: unknown RR
type 'siyongc.domain.'
Nov 16 15:07:44 rh71 named[2422]: dns_zone_load: zone siyongc.domain/IN: loading
master file siyongc: unknown class/type



如下的问题,那可能是您没有定义 SOA 记录,或设定有错误:

Nov 16 15:14:33 rh71 named[2506]: dns_zone_load: zone siyongc.domain/IN: could
not find NS and/or SOA records
Nov 16 15:14:33 rh71 named[2506]: dns_zone_load: zone siyongc.domain/IN: has
0 SOA records
Nov 16 15:14:33 rh71 named[2506]: dns_zone_load: zone siyongc.domain/IN: no
NS records



下面的问题可能是您的 SOA 记录中多输入了一组数字,或少输入了一组数字,或数字格式有错误:

Nov 16 15:14:33 rh71 named[2506]: dns_zone_load: zone siyongc.domain/IN: could not
find NS and/or SOA records
Nov 16 15:14:33 rh71 named[2506]: dns_zone_load: zone siyongc.domain/IN: has
0 SOA records
Nov 16 15:14:33 rh71 named[2506]: dns_zone_load: zone siyongc.domain/IN: no
NS records

Nov 16 15:18:24 rh71 named[2562]: dns_rdata_fromtext: siyongc:4: near eol: unexpected
end of input
Nov 16 15:18:24 rh71 named[2562]: dns_zone_load: zone siyongc.domain/IN: loading
master file siyongc: unexpected end of input

Nov 16 15:19:34 rh71 named[2640]: dns_rdata_fromtext:
siyongc:4: near '14B400':
syntax error
Nov 16 15:19:34 rh71 named[2640]: dns_zone_load: zone
siyongc.domain/IN: loading
master file siyongc: syntax error



以下问题可能是 SOA 的 “ ( ) ”符号有问题,要么是“ ( ” 给断到下一行了,要么是“ ) ”给批注掉了:

Nov 16 15:22:08 rh71 named[2669]: dns_rdata_fromtext: siyongc:3: near eol: unexpected
end of input
Nov 16 15:22:08 rh71 named[2669]: dns_zone_load: zone siyongc.domain/IN: loading
master file siyongc: unexpected end of input

Nov 16 15:22:52 rh71 named[2696]: dns_rdata_fromtext: siyongc:4:
near 'IN': extra input text
Nov 16 15:22:52 rh71 named[2696]: dns_zone_load: zone siyongc.domain/IN:
loading master file siyongc: extra input text



以下是您没有设定 NS 记录或 NS 记录设定有错误:

Nov 16 15:25:30 rh71 named[2801]: dns_zone_load: zone siyongc.domain/IN: no NS records



下面的错误可能是您设定了一个记录项超出了当前 ORIGIN 的范围,例如 localhost. 或 siyongc. (也就是错误使用 FQDN );或是错误的使用了 $ORIGIN 设定;或是在 named.conf 中有多个 zone 在分享同一份记录文件:

Nov 16 15:31:20 rh71 named[2920]: dns_master_load: siyongc:16:
ignoring out-of-zone data



下面的错误,有可能您在设定多个 $ORIGIN 并同时尝试设定多个 SOA 时出现的错误:

Nov 16 15:28:31 rh71 named[2855]: dns_master_load: siyongc:26:
not at top of zone



许多许多问题,事实上您都可以在 /var/log/messages 中找到,当您发现这些错误信息之后,看看是关于什么记录的,然后顺藤摸瓜,留心一下档案内容,就比较容易找到错误的原因了。

有时候,您想简化您的 DNS 设定工作,您可以使用 netconf 来做。不过,根据我的经验是:netconf 未必能够完全帮您正确的设定起来。当您重新启动 named 之后,别忘了看一下 /var/log/messages ,确定没有错误发生。如果您使用工具来设定 DNS 而碰到问题,这就需要您有手工设定的能力了。



设定 DNS Client

DNS 系统是一个典型的 Client/Server 架构,前面介绍的动作仅是确保 DNS 的 server 成功启动起来而已,如果您要测试它,还必须设定好 client 端才行。

不知道您会不会设定 linux 的 dns client 呢?如果忘记了要打屁屁了哦~~~ 事实上我们在第一章的“网络设定”那里就设定过了,也就是修改 /etc/resolv.conf 这个档案,将您刚设定好的 DNS 主机 IP 放在档案的前排位置,如:

nameserver192.168.100.23
nameserver168.95.1.1
nameserver139.175.10.20
domainsiyongc.domain
searchsiyongc.domain dmz.domain test.com



假如您的 client 和 server 在同一台机器上,那可以将第一个 name server 设定为 0.0.0.0 或 127.0.0.1 。

要是您使用 Windows ,但不是透过 DHCP 来指定 DNS 的话,那您或许需要手工设定了:控制台 --> 网络 --> TCP/IP (-> 网络卡) --> 内容 --> DNS 组态 :



请注意:如果您修改了这里的设定,就算您的 Windows 是透过 DHCP 取得 IP 设定的话,也会以这里的设定为准。如果您想使用 DHCP 的设定,那就选择“关闭 DNS”吧。



测试 DNS

要测试我们的设定是否生效,我们可以使用的方法有很多,其中最简单的莫过于 ping 命令了。直接 ping 一下您所预期的 dns 名称就知道结果了。

不过,ping 毕竟很有限,例如:您不能查询 MX 和 NS 等记录。实作上,我们最最常使用的 DNS 查询工具是 nslookup 命令。关于 nslookup ,在“学习网络”的“DNS 协议”文章中有很详细的例子,这里不再重复。如果我们在测试中失败,例如 nslookup 响应说:

*** rh71.siyongc.domain can't find XXX.XXXX.XXXX:
Non-existent host/domain



这通常是反解记录没设定好的缘故,请确定 DNS 主机本身的反解有设定起来,而且可以被 DNS 追查得到。如果反解没有授权下来,那就请上游 ISP 帮忙设定。不过,我发现这个错误信息似乎在新版的 nslookup 中不会出现,anyway ,请您自己留意吧。

有时候 nslookup 会停在某处一动也不动,其实它不是当掉了,而是在查询没结果之后等 time out 而已。您可以按 Ctrl + C 终止查询,再打 exit 跳出来。不过,如果您在按了 Ctrl + C 之后接着再输入一个无结果的查询,那就好可能将 nslookup 当掉。这样您可能要登录进另外一个 terminal ,然后用 kill 将 PID 杀掉。同上,新版的 nslookup 没有这个困绕,但如果按 Ctrl + C 的话,则会直接跳离 nslookup 程序。

然而,nslookup 似乎在以后的版本中不再维护了,取而代之的,就是 dig 命令,所以,当您在 Redhat 7.1 上输入 nslookup,您会看到如下这样的信息:

Note: nslookup is deprecated and may be removed from future releases.
Consider using the `dig' or `host' programs instead. Run nslookup with
the `-sil[ent]' option to prevent this message from appearing.



这段文字不用解释了吧?真的不知道说什么就查字典吧~~ 这里,我们不妨学习一下如何用 dig 来查询和测试 DNS 服务。

基本上,dig 命令的语法如下:


dig [@server] domain [<query-type>] [<query-class>] [+<query-option>]
[-<dig-option>] [%comment]

看起来蛮复杂的,恐怕要 man dig 才知道怎么使用。不过,我们平时只用它来查询 dns 数据的话,要使用到的选项也不会太多啦,如果您会得在 nslookup 中设定 type=XXX 的话,那您也可以用 dig 来查询不同的记录类别数据。例如:

# dig siyongc.domain mx

; <<>> DiG 9.1.0 <<>> siyongc.domain mx
;; global options: printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 8198
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 2, ADDITIONAL: 2

;; QUESTION SECTION:
;siyongc.domain. IN MX

;; ANSWER SECTION:
siyongc.domain. 86400 IN MX 20 lp64.dmz.domain.
siyongc.domain. 86400 IN MX 10 rh71.siyongc.domain.

;; AUTHORITY SECTION:
siyongc.domain. 86400 IN NS lp64.dmz.domain.
siyongc.domain. 86400 IN NS rh71.siyongc.domain.

;; ADDITIONAL SECTION:
rh71.siyongc.domain. 86400 IN A 192.168.100.23
lp64.dmz.domain. 86400 IN A 10.0.1.130

;; Query time: 8 msec
;; SERVER: 192.168.100.23#53(192.168.100.23)
;; WHEN: Fri Nov 16 21:13:18 2001
;; MSG SIZE rcvd: 138



上面是的命令是使用预设的 name server 来查询 siyongc.domain 的 mx 记录。当然,您也可以用 @ 来指定用某一台 name server 来查询其它的信息。例如,我要用 hinet 的 dns 来查询负责 com.tw 的 NS 有哪些:

# dig @168.95.1.1 com.tw ns

; <<>> DiG 9.1.0 <<>> @168.95.1.1 com.tw ns
;; global options: printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 33339
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 4

;; QUESTION SECTION:
;com.tw. IN NS

;; ANSWER SECTION:
com.tw. 518400 IN NS b.twnic.net.tw.
com.tw. 518400 IN NS c.twnic.net.tw.
com.tw. 518400 IN NS a.twnic.net.tw.

;; ADDITIONAL SECTION:
b.twnic.net.tw. 159497 IN A 192.72.81.200
c.twnic.net.tw. 159497 IN A 168.95.192.10
a.twnic.net.tw. 159497 IN A 163.28.1.2
a.twnic.net.tw. 159497 IN A 140.111.1.2

;; Query time: 167 msec
;; SERVER: 168.95.1.1#53(168.95.1.1)
;; WHEN: Fri Nov 16 21:17:46 2001
;; MSG SIZE rcvd: 146



除了用 nslookup 和 dig 之外,如果您只想简单的查询 dns 信息的话,那您可以用 host 命令。例如:

# host -t any siyongc.domain 0.0.0.0
Using domain server:
Name: 0.0.0.0
Address: 0.0.0.0#53
Aliases:

siyongc.domain. SOA rh71.siyongc.domain. root.rh71.siyongc.domain. 2001111601 28
800 14400 3600000 86400
siyongc.domain. name server lp64.dmz.domain.
siyongc.domain. name server rh71.siyongc.domain.
siyongc.domain. mail is handled by 10 rh71.siyongc.domain.
siyongc.domain. mail is handled by 20 lp64.dmz.domain.
siyongc.domain. has address 192.168.100.23



上面的命令就是用本机 name server 来查询 siyongc.domain 的 any 信息。至于 host 命令的格式如下:


host [-aCdlnrTwv] [-c class] [-N ndots] [-R number] [-t type] [-W wait]
name [server]

老话啦,看 man host 以了解那些参数和选项的用法吧。

您可以发现:透过 nslookup 、 dig 、与 host 命令,事实上可以查询到许多 dns 上面的设定信息。所以,如果您的 DNS 是对外提供服务的话,请尽量尽量控制 DNS 信息量,如果您觉得没必要对外提供的,那就拿掉它。无论如何,关于内部网络的 DNS 信息,是绝对不能对外散布的。如果查询的结果未如您所预期的,您就要进行 debug 工作了。



注册 domain

Okay,相信到此为止,您已经能够在单一的 dns 上面设定一个或多个 domain 的正解和反解服务了。这时候,您或许早已迫不及待想注册一个属于自己的 domain 来玩玩看吧?

呵呵~~ 有此冲动绝对正常,尤其现在的 domain 注册那么方便和便宜,前几天在‘讨论园地’得知原来现在注册一个 .com 或 .org 的网站,一年都不用 $10 块美金!实在是便宜得令人难以至信~~~ 如果您贪图方便的话,可以请任何一家网络公司代您申请 domain (当然需额外的服务费);要不然呢,也可以直接到网络上完成自己的 domain 注册。

不过,要注册自己的 domain 之前,有些条件您还是要准备好的:


还没被注册走的 domain 名字;
贵 domain 的拥有人、负责人、发票人、管理员 之姓名、住址、和联络数据(皆英文);
管理贵 domain 的 ns 主机,必须有固定 IP (最少要两台,可请别人代管);
合法有效的信用卡,而且您愿意在网络上使用它。

当您这些条件都符号之后,可以联机到网络上的著名 domain 服务网站,例如:


http://www.netsol.com/
http://www.dotster.com/
http://www.godaddy.com/
http://www.twnic.net/

当然,还有很多很多~~~ 而最后一个网站是负责台湾的 domain 注册的机构,您可以到那里注册所有以 tw 结尾的 domain,除了 twnic 之外,很多 ISP (例如 seednet )也有提供 tw domain 的注册服务。

各网站的注册手续和表格或许不尽相同,但基本上您需要提供的信息还是大同小异的,我这里就不介绍如何进行了,只要您身边有字典都没问题啦~~~ 在您所提供的信息中,其中有一项比较伤脑筋的,就是 ns 主机要指向哪里?(注册时需要最少两台)

以正规的手续来说,如果您要用一个 IP 来作为您的 name server,您必须先要将这个 IP 在 whois 数据库中注册为 NS 记录才能使用,假如该 IP 或是该 NS 已经注册过了,您就不能按您的意思来注册了,但您可以使用它(当然您要确定您能管理那台注册主机,或是获得对方的管理员同意)。但我这里告诉您一个秘诀:第一次注册 domain 的时候,随便设定都可以!(哦,这是我在 dotster 上面的经验啦,其它网站是否如此我就不清楚了~~) 然后您在完成注册后,用您的账号进去修改 name server 的 IP 就可以了(当然,您要设定的 IP 必须还没被注册过,或已经从 whois 数据库中注销)。

然而,如果您日后要变更您的 NS 和 IP 的话,是很麻烦的一件事情!而根据我以往的经验,您最好用 email 和网站的支持人员取得联络,才能顺利完成修改。嗯,这种工作实际上一点也不好玩啦,而且各网站有各自的方法和表格。比方说,如果您透过 networksolution 注册的话,日后您要修改 name server,必须填写 host FORMs,然后会根据您提供的确认方式确认之后才能完成,他们的确认方式有三种:


MAIL FROM:以您所提供的 email 信箱为依据;
CRYPT-PW:以您提供的密码为依据;
PGP:以您的 PGP 签名为依据。

不过,在实作流程上非常复杂,比方说,如果原本采用 MAIL FROM 方式,但后来您的 email 信箱却变更了,那就很麻烦了,因为对方不能根据您的新 email 信箱来作为确认依据的。我曾经为所服务的公司修改过 NS 记录,到最后,只能以 fax 的方式来解决。

而像 dotster 网站,则只能透过账号进行在线修改。这原本很方便,但最不好的地方是:他们不提供确认信息!往往,您以为已经修改完毕,但等了一个星期还没生效,去信问他们,才知道原来要修改的那个 IP 并没有注册为 ns 主机,或已经注册在别的名称下面了。我曾经数次写信给 doster 的 support 信箱,要求他们在在线修改后要向用户提供确认信息(不管成功与否),但不知道他们现在是否有改善了呢?(如果还没改变的话,请大家多作投诉,直到他们提供确认服务为止。)


Tips:如果您在 dotster 或其它网站修改 NS,而不能成功的话,请穷追他们的 support 信箱就是了。通常他们都会帮您搞定的,而且提供的信息比较满意。例如,如果您要修改的 IP 还没注册,他们会帮您完成注册(注意哦,name server 的 host 注册和您的 domain 注册可是不同的哦~~)。

但我也曾经试过到 networksolution 上面注册一个 new host,然后到 dotster 那边修改,也能顺利完成!但这个后门,不知道现在是否还行得通呢?


说实在,就算您注册了 domain,如果您没有固定 IP 的话,最好不要自己管 DNS ,请别的有固定 IP 的朋友帮忙,或是付费请人代管就是了。而上面提到的 domain 网站,大都提供这样的服务。

另外,还有一个概念或许是许多 DNS 新手容易搞混乱的:我们这里所说的 domain 注册,在整个 DNS 系统中,仅属于“正解”方面的注册和授权而已;这和“反解”的授权毫不相关。而反解的授权,因为是跟据 IP 授权的,所以必须透过您的 IP 发放机构进行。换句话说:反解的授权,只能透过 ISP 进行。请您一定要区分这两种授权模式。



关于 Dynamic DNS

如果您还没有固定 IP 而又想让别人能够透过 DNS 来查询主机的话,您可以到网络上申请所谓的‘动态 DNS ’服务,大部份都是免费的,而且也有多种平台的 client 程序提供。如果您有兴趣,可以找到很多这类网站,下面只是其中两个:


http://www.dyndns.org/
http://dns2go.deerfield.com/
http://www.adsldns.org:8080/service.php (中文)

如果您不知道如何申请和安装这类动态 DNS 的话,您可以参考如下网页:


Steven 计算机世界 之“Linux 使用 ADSL (计时制) 的经验分享”
鸟哥的 Linux 与 ADSL 文件 之 “动态 DNS 申请 ”

Tips:如果您使用拨接式 ADSL (PPPoE) 并在 adsldns.org 上面完成注册之后,您只需在 /etc/ppp 目录下面修改一个 ip-up.local 档(如果没有请自行建立),增加如下内容:

#!/bin/bash
CMD="http://www.adsldns.org:8080/clientupdate.php\
?email=XXXXX@XXXXXX&passwd=XXXXX\
&hostname=XXXXXX.adsldns.org&debug=1"
lynx -dump $CMD > /tmp/adslclient.log



(注意:请将 XXXXX 修改为您的正确数据。同时,首两行结尾的 \ 符号不要漏了,其左右没空白;要不然,拿掉 \ 符号并将前面三行写成一行。)

然后,只要您完成 ADSL 拨接之后,就能‘自动’的帮您修改 IP 记录了!


关于动态 DNS 的应用,除了上述的环境之外,在 DHCP 分配的网络中设定 DNS 也可以应用得上。但前提条件是:您的 named 必须是 bind 9.x 或以后,以及 dhcpd 必须是 3.x 或以后的版本。然而,RedHat7.1 上面预装的 dhcpd 是 2.0p15-4 这个版本,您必须自行升级才能使用这个非常棒的功能。

下面,我将 dhcp 服务转移到 mandrake 8.1 (其预装的 dhcpd 版本是 3.0-0.rc12.1),然后保留 named 在 rh71 上面,再透过 ddns 技术更新和维护 dhcp 所发放的 DNS 数据。我初步整理出来的步骤如下:


在 mdk 上执行如下命令,产生 dns 加密验证所需的 secret :

dnssec-keygen -a HMAC-MD5 -b 128 -n HOST DHCP_MDK


这样会在当前目录下产生两个以 Kdhcp_mdk 开头的档案,有兴趣您可以看看其中的内容。然后您将 Kdhdp_mdk*.private 中的最后一行 Key: 后面那串字符串复制下来 (如:4sxutdFuNMqF1B0Q2GV1uQ==),待会要用到。


然后修改 /etc/dhcpd.conf 的内容,类似如下:

ddns-update-style ad-hoc;# 这行一定要加上

subnet 192.168.100.0 netmask 255.255.255.0 {
......# 其中内容略,请自行填写
}

key DHCP_MDK {
algorithm HMAC-MD5.SIG-ALG.REG.INT;# 加密算法名称
secret 4sxutdFuNMqF1B0Q2GV1uQ==;# 这就是上一步骤产生的 key
}

zone siyongc.domain. {
primary 192.168.100.23;# 指向 name server 所在地址
key DHCP_MDK;# 必须和前面的 key 名称一致
}

zone 100.168.192.in-addr.arpa. {
primary 192.168.100.23;# 同上
key DHCP_MDK;
}



然后重新启动 dhcpd 的服务,并确定其功能正常。关于更多的设定,请 man dhcpd.conf ,搜寻 ddns 子串就可以找到。


然后转移到 rh71 上面,修改 /etc/named.conf ,在 options 前面加上如下句子:

key DHCP_MDK {// 这段应该和 dhcpd.conf 设定一致
algorithm HMAC-MD5.SIG-ALG.REG.INT;
secret 4sxutdFuNMqF1B0Q2GV1uQ==;
};

logging {// 这是记录设定
channel update_debug {
file "/var/log/update-debug.log";
severity debug 3;
print-category yes;
print-severity yes;
print-time yes;
};
channel security_info {
file "/var/log/named-auth.info";
severity info;
print-category yes;
print-severity yes;
print-time yes;
};

category update { update_debug; };
category security { security_info; };
};



然后再为相应的 zone 加上 update 设定:

zone "siyongc.domain" {
type master;
file "siyongc.domain";
allow-update { key DHCP_MDK; };// 名称必须和前面的 key 一致
};
zone "100.168.192.in-addr.arpa" {
type master;
file "192.168.100.rev";
allow-update { key DHCP_MDK; };// 同上
};



然后建立所需的记录文件:

touch /var/log/update-debug.log
touch /var/log/named-auth.info
chown named.named /var/log/update-debug.log
chown named.named /var/log/named-auth.info


完成后请重新启动 named ,并检查 /var/log/messages 及测试服务是否正常。


最后,就是等待记录更新了~~~ 哦,我忘了准确的更新时机了,我在某处看到过(记不起来了:家里的书?书局的书?网络上?):更新的时机好像是 dns 那边累积 100 了一百个记录在 journal 的时候;或是每隔 60 分钟 (哪个标准先到达就采用哪个方法,不过,真的记得不是很清楚)。如果您在 /var/named 的记录文件下面发现更新(标志其一是 Serial 号码),或是在 /var/log/update-degub.log 上看到有记录。那就成功了!


如果一直没动作怎么吧?呵呵~~~ 我也不知道。但我会建议您将 /etc/dhcpd.conf 、named.conf、和 /var/named/ 的记录文件尽量简化,将那些有的没的全部拿掉,并重新启动服务看看。当然了,/var/log/ 里面记录文件也有很多重要信息,比方说提升 named.conf 里的 debug level 数值(如:severity debug 9 ),然后执行:

tail -f /var/log/update-dbug.log


再不然,用 tcpdump 抓封包看啰~~~


老实说,我原本写这篇文章的时候并没有打算将 dhcp + dns 的动态更新写进来的,因为还没实作过。幸得在新闻组上得到 小州兄的指点,才装了个 Mandrak8.1 ,并按 man page 的步骤设定起来的。我觉得在本机上更新,也就是 dhcpd 和 named 都在同一台机器上,会比较容易成功。如果跨网络进行的话,那您得要首先解决网络想过的问题,例如路由和防火墙这些设定。

Anyway,我不敢保证您能按照上面的步骤实作出来,总要自己多尝试尝试吧。如果您想更进一步了解 DNS 的动态更新,您可以研究一下 nsupdate 这个命令。它可以让您以交谈模式来更新 named 的记录设定。


Tips:我知道许多所谓的动态 dns 服务,大都会于 server 上提供更新机制,我猜,只要透过简单的 cgi 或 client 程序,就应该可以完成的。看完下面 Leo 兄的文章,您应该会有灵感的:




动态 DNS 设定技巧

除此之外,如果您还有兴趣研究动态 DNS 技术的话,不妨到网络上找找 IXFR 的技术,也可以参考如下这些 RFC:1034,1995,1996,2136,2535,2694。

设定 master / slave

不管您是否有打算注册自己的 domain 和管理自己的 DNS 主机,在您真正架设对外服务的 dns 服务器之前,请先行在内部网络架设看看,直到您有信心之后才架设直接向 Internet 提供服务的 DNS 。而您需要练习的这些前置功夫中,其一就是 master 与 slave DNS 的设置。

假如您真的到网络上注册过 domain,他们通常需要您提供最少两台 NS 主机。为什么呢?这是基于备援考虑的。当一个注册 domain 同时授权到两台 ns 上面管理的话,那别人透过 DNS 查询的时候,会获得两个 NS 记录( root zone 就有 13 个 ns 之多!)。对方只需向其中一台进行查询就可以了,如果第一台不能成功的话,则转向下一台。究竟向哪一台 NS 查询,其先后顺序没什么关系,但关键的是数据的准确性!

在前面您已经知道如何在单一的主机上面进行 DNS 设定了,那么,当有两台主机需要为同一个 domain 提供 DNS 服务的时候又如何设定呢?您当然可以在两台主机上各设定一次。但数据的同步呢?您总不能在一台 NS 查询到一个 IP 地址、而在另一台 NS 得到另外一个地址吧?如果发生数据变更需求的时候,您也得同样的在两台机器上面进行修改,而且必须透过人为的观测,以确定双方的数据一致性。那~~ 是否有更好的办法来做到这点呢?

当然有啦,这就是 master 和 slave DNS 的设定了。透过 master 和 slave 的架构,您日后要进行数据变更的时候,只需在 master 上面维护就好,然后 slave 会定期的自动过来将更新数据同步回去(还记得 SOA 那堆数字的吗?您应该知道 Refresh 和 Serial 的作用吧?如果您忘记了,请回去温习一下)。

如果您没有理解错误,应该知道 slave 会在 refresh 时间到达的时候,就尝试和 master 进行数据同步的动作,这在 DNS 系统里面有一个专门术语,叫做“zone transfer”(区域转移),而在技术层面来说,则是 AXFR 查询:


当 slave 需要进行 zone transfer 之前,它首先查询 master 的 SOA 记录之 serial 数值;
如果发现数值比 slave 上的 serial 要大,就送出 AXFR 查询;
如果 master 允许 slave 的 zone transfer ,那就响应 AXFR 的查询结果;
然后 slave 根据查询结果更新自己的记录文件。

从上面的流程来看,您不难发现 serial 在整个区域转移过程中的重要性。所以,您每次修改了 master,一定要将增加 serial 数值。虽然,您可以依序的增加数值,但如果您的 Serial 号码是依照“日期 + 修改次数”格式的话,那么您只要修改日期部份,就肯定可以获得一个更大的数值(除非您又碰到 Y2K 的问题 );假如您的修改是在同一天发生的,那您可以修改最右边的两为数字(相信您一天之内不会修改 100 次吧?)。

要设定 slave DNS 其实非常简单,简单到或许您不相信!真的没骗您,您只需在 slave 主机上面的 /etc/named.conf 增加这几行就可以了:

zone "siyongc.domain" IN {
type slave;
masters { 192.168.100.23; };// 请不要漏了 masters 后面的 s !
file "slave.siyongc.domain";
};



一点也没错!就这么简单~~~ 我们假设上面的设定在 10.0.1.130 ( lp64 ) 上面进行,而 master 则是 192.168.10.23 ( rh71 )。这里,我再告诉您一个您非常乐意听到的信息:您根本无需担心如何建立 slave 的记录文件,named 会自动帮您搞定!您只需确定 /var/named 这个目录能够被 named 写入就行了。如果您不确定,那只需将目录的 owner 改一改就行了:

chown -R named.named /var/named


这样的话,只要 slave 的 refresh 时间到达,就会自动的帮您更新记录数据了(当然了,底层的路由和联机必须是畅通无阻的)。但是,每次当您修改了 master 上面的设定并重新启动 named 服务的时候,master 就会主动向资源记录当中的所有 NS 主机送出 NOTIFY 信号(自己除外,但 master 的 NS 记录必须是第一笔)。当 slave(s) 收到来自 master 的 NOTIFY 之后,会回复一个确认给 master ;然后根据 /etc/named.conf 档案中的设定,尝试向所定义的 masters 地址进行 zone transfer (是否要更新数据,当然还必须以 Serial 为依据),就好像 refresh 到达了一样。


Tips:假如您发现修改 master 后并不能及时同步 slave 上的数据,那可能是 slave 并没写在 NS 记录上。如果您不愿意修改 NS 记录,那您可以在 master 的 named.conf 里面的 zone 设定上加上这几行:

zone "siyongc.domain" IN {
type master;
file "siyongc.domain";
notify yes;
also-notify { 192.168.100.26; };
};



这样,master 在修改后同时还会通知名单中的 slave 主机。

事实上,如果有别的 slave DNS 被设定为指向该这台 master 的话,就算您这里将 notify 设为 no ,当 slave 主机的 refresh 到期的时候,还是可以进行区域转移 (zone transfer) 的。

当然了,为了防止别人任意的向 master 进行 zone transfer 而盗取 zone 数据,named 还允许您以 acl (Access Control List) 来控制哪些主机才能上来进行区域转移(这个我们后面再谈),同时,还允许 zone transfer 的时候以加密的方式传送数据。


除了上述的备援需求外,在其它情形也有可能需要 master / slave 的架构。比方说,您有一个很大型的网络,如果所有主机都集中向 master 进行 DNS 查询,那势必会增加 master 的工作负荷、而降低其效能,同时也产生额外的远程网络流量。这时,您最好设定多台 slave 放置在不同的地点来分担 master 的工作,同时也能提供备援服务。



设定 forwarder

我们除了能够用 slave 来分担 master 工作、减少网络流量之外,还可以透过另外一种 DNS 机制来减低网络流量的,那就是 forwarder 设定了。

所谓的 forwarder ,就是当某一台 NS 主机遇到非本机负责的 zone ( slave zone 也属于本机负责的范围) 之查询请求的时候,将不直接向 root zone 查询而把请求转交给指定的 forwarder (一台或多台) 主机代为查询。如果您不了解 DNS 的查询模式,那您很难理解这个 forwarder 的意义和好处。

我们知道,当 NS 主机在接到 client 的查询的时候,首先会检查这个查询是否属于本机管辖,否则将转向 root zone 再逐级的查询下去,最后将结果告诉 client 。而在这个过程之中,NS 主机还会将每一笔结果存放到 cache 中。这样,只要 cache 中的 TTL 没过期的话,在下次遇到同样查询的时候,就可以直接将结果响应给 client 了,而无需再重复上次的查询流程。如果 NS 上面指定了 forwarder,那这个 NS 发现 cache 没有记录的话,将不向 root 查询,而是将自己扮成一个 client,向 forwarder 送出同样的请求,然后等待查询结果;而逐级往下查询的动作,则交由 forwarder 负责,NS 自己就轻松多了。但无论这个结果是自己直接查询得来的,还是 forwarder 送回来的,NS 都会保存一份数据在 cache 中。这样,其后的相同查询就快多了,这对于 NS 所服务的 client 而言更是有效率得多。

但是,假如您仔细研究一下这个 forwarder 机制,您会发现它的好处并非仅是上面所提到的效能提升,而且,对于整个网络流量(尤其是对外的流量)也有非常正面的帮助。比方说,您的内部网络需要 10 台 DNS 来提供服务,您只需在某一台能直接与外界沟通的计算机上架设 DNS 服务,然后将其它内部 NS 的 forwarder 指向该主机就行了。这样,本来需要 10 次的 root 查询,在 forwarders 的机制下,就只需 1 次而已!连同下层的往返查询来计算的话,总体上所省下的对外查询就更多了~~ 如果再加上 cache 的效能,forwarder 所降低的 DNS 流量是非常显著的。

事实上,forwarder 在我们的实际应用中也很常见,例如,我们只要将 forwarder 设定为 ISP 的 DNS ,那么,我们的 NS 就无需直接向 root 查询了;又因为 ISP 上的 DNS 也有 cache 的关系,所以我们的 NS 所获得的查询结果,也比直接向 root 查询来得要快。

如果您打算使用 forwarder 的话,您可以在 /etc/named 的 options { } 里面加入这样的句子:

forward first;
forwarders {// 别漏了最后的 s !
139.175.10.20;
168.95.1.1;
};



您或许从上面的设得知的这台 NS 主要是对外联机的,假如您的主机是内部的其它 NS,那就集中指向对外的 NS 就好了。

然而,上面的设定由于是在 options 里面设定的缘故,这样会让所有非本机的查询都转向 forwarder 。假如您不想这样做,而只是针对个别的 zone 设定 forwarder 的话,那您也可以这样设定:

zone "siyongc.domain" IN {
type forward;
forwarders { 192.168.100.23; 10.0.1.130; };
};



这样,在这台 NS 主机上面,所有关于 siyongc.domain 的查询,都将转交到 192.168.100.23 或 10.0.1.130 那边去。



设定子网域授权

到这里,您所需要具备的 DNS 技巧相信已经足够应付普通网络的需要了。但如果您的网络非常庞大,而且 DNS 系统比较复杂,或是您有兴趣知道 Internet 上是如何进行 DNS 授权的话,那您或许需要了解一下 DNS 的子网域 (sub zone) 授权设定。

这个问题不如用实际的例子来说明好了。正如您从本章所看到的范例,目前我在 rh71 上面已经设定有两个 domain 的 zone :siyongc.domain 和 dmz.domain 。假设我现在要在 siyongc.domain 分出一个 sub-zone,称为 home.siyongc.domain ,同时将这个 sub-zone 授权给一台叫 diamond 的主机来管理;目前 diamond 上面有两张网络卡:192.168.100.26 和 192.168.2.1 ,而 home 这个 sub-zone 需要管理的 DNS 除了 diamond 本身外,还有 pc100 到 pc200 ( IP 范围从 192.168.2.100 到 192.168.2.200 之间) 等主机,他们都是由 DHCP 发放的。当然了,底层的网络连接,例如 hub、路由、防火墙、等等,都已经设定好了。那么,我们要如何进行呢?

首先,我需要修改 rh71 上的 /var/named/siyongc.domain 挡案,将 home 授权给 diamond.home.siyongc.domain 这台 NS 来管理,您只需在记录文件后面增加这些句子就可以了:

;; -- sub zones --
$ORIGIN home
@ IN NS diamond.home.siyongc.domain.
diamond IN A 192.168.2.1



上面我用一个 $ORIGIN 来宣告一个属于 siyongc.domain 范围内的 sub-zone 叫 home (如果改用带小数点的 FQDN 的话,则写成 home.siyongc.domain. ),以及负责这个 sub-zone 的 NS 主机,还有 NS 主机的 IP 地址所在。这里的 NS 记录就是用来授权用的了!目前我只授权给单一一台 NS 而已,如果您喜欢,那您可以授权多台 NS 主机。事实上,当您在网络上注册 domain 的时候,他们也是在上游(如 com. 或 com.tw. ) 那边帮您设定 NS 记录和 NS 主机的 A 记录而已~~~


Tips:假如您不使用 $ORIGIN 的话,那可以取消这行,然后将 @ 改为 home ,以及将 diamond 改为 diamond.home 就可以了(注:两个记录名称都没有小数点!)。

接下来的设定,需要转到 diamond 上面进行。首先,修改 /etc/named.conf 档案,增加如下数行:

zone "siyongc.domain" IN {// 上一级区域设定
type forward;
forwarders { 192.168.100.23; };
};

zone "home.siyongc.domain" IN {// 本机管辖区域设定
type master;
file "home.siyongc.domain";
};



这里,您或许发现我用 forwarder 将上游的查询转向正确的位置(当然,您直接在 options 里面指定 forwarders 也可以),您应该知道这样做的好处了吧?除了无需绕到 root zone 往下查询下来之外,更重要的原因是:这个 sub-zone 主机和上游主机不是同一台 NS ,除非这两台主机同时是 internet 的合法 IP 且经过注册(换句话说:父网的 NS 主机可以从 root zone 查询下来),否则的话,它就查询不到其它 sub-zone 的记录了!除了用 forwarder ,另外还有一个方法是:就是架设 slave 主机以获得上游的 zone 数据。不管用哪一种方法,如果您不能查询到上游 NS 的话,您就没办法查询其它 sub-zones 了。

除此之外,我们还必须建立 /var/named/home.siyongc.domain 这个档案,内容如下:

$TTL 86400
$ORIGIN home.siyongc.domain.
@ IN SOA diamond.home.siyongc.domain. root.diamond.home.siyongc.domain. (
2001111701 28800 14400 3600000 86400 )
IN NS diamond.home.siyongc.domain.
600 IN MX 10 diamond.home.siyongc.domain.

;; -- servers --
diamond IN A 192.168.2.1
IN MX 0 diamond.home.siyongc.domain.

;; -- workstations --
$GENERATE 100-200 pc$ A 192.168.2.$



在这里,我首先将 MX 的 TTL 降为 10 分钟,因为我目前还不很确定这个 sub-zone 的邮件是否由 diamond 来管。如果不增加 600 这个字段的话,那么 TTL 会以前面的 $TTL 值为准,也就是一天。然则,一旦有别的 DNS 查询过这个 MX 记录,那么这个记录会在对方的 cache 中存在一天时间。假如我日后修改 MX 记录的话,那我很可能要等一天之后,才能让别的 DNS 查询到新的设定值。


Tips: 事实上,在您进行任何 DNS 记录的修改,都必须认识到 TTL 的重要性以及它可能产生的影响,这点,我在本章最后再谈。

然而,在这个档案中,您首次接触到 $GENERATE 这个选项。如果您有写过 shell script,或是具有“变量 (variable) ”概念的话,这行一点都不难理解:


首先,我用 $GENERATE 产生一段数值范围,您可以将之当成一个变量数组( array )。注意:这段数值并不能直接用来作记录项;
然后,在这个句子后面的“ $ ”符号就是变量数组里面的值(还记得 for 循环吗?如果忘记了,请回去 system 系列那边补习 shell 的知识);
其后,我所定义的 pc$ 才是记录项名称的开始:它的意思就是定义一个 pcXXX 的名称,而 XXX 的值就是 $ 。
那后面的 A 呢?您应该知道什么是 A 记录类别了吧?(不过,我觉得奇怪,这个版本竟不接受“ IN A ”这样的设定!不知道新版有没有解决了?)
同样道理,192.168.2.$ 的那个 $ ,和 PC$ 那个 $ 是同一样的值。

不难理解吧?换而言之,如果您不使用 $GENERATE 的话,那就为 pc100 到 pc200 这 100 台主机设定 100 行 A 记录就是了。那么,请问:您愿意用那个方法呢?


注:假如您已经在 Internet 上注册了一个合法的 domain ,那么您在这个 domain 下面切分出去的 sub-zone 就无须再注册了。因为您的 domain 所使用的 zone 已经获得授权,并且也有自己的 SOA ,那么其下要再授权出多少个 sub-zone,或往下授权多少层,完全由您自己作主。



设定子网反解授权

好了,刚才介绍的 sub-zone 授权,是属于正解部份的,那么反解又如何呢?通常来说,如果您获得的 IP 是一整段 class (或 A 或 B 或 C ) 的话,在反解设定上也不会太难就是了。我相信聪明的您一定已经知道如何设定吧?(前面不是设定过了吗?)

如果您真真正正了解 IP 和 Net mask 的关系,那我这里要出一道难题了:我在我的网络设定中,10.0.1.0 这个网络实际上借用了 3 个 bit 来切割成 8 个子网络。而我将这台 rh71 上其中一个界面分配到 sub-net ID 为‘100’的这个子网中,也就是说,实际的 Net ID 应该是‘10.0.1.128’;而另外一个界面则分配在 10.0.1.0/27 这个子网络中。

在前面,我们已经设定过 0.1.10.in-addr.arpa 的反解了,但那次只是单纯的为整个 C Class 做反解,事实上并没考虑到 sub-net 的问题。现在我打算将这个网络的反解再进行子网络的授权设定。我暂时保留 10.1.0 这个‘父网’的反解,然后将 128 这个子网的反解授权给 10.0.1.130 ( lp64 ) 上面进行(至于其它网暂时不设定了,反正只要会了设定其中的一个,就能举一反三)。


Tips:对于切割子网的 DNS 反解设定,是非常难懂的,您一定要对 IP 地址划分有很清晰的了解,要不然,请您先搞定 IP 的 subneting 再回来(可参考“学习网络”中的 “ IP 地址 ”一文)。在以后的叙述里,请务必留神!如果您不想弄那么复杂,最简单莫过于在“父网”上面做好所有子网的记录设定(像是请 ISP 那边帮忙设定反解一样)。但问题是,如果子网那里要进行变更,就一定要劳烦上级网络管理员,网络的灵活性当然就大打折扣了。

或许,在一开始弄 DNS 的时候就把子网带进来,会显得过于艰难。我这里建议您大可先将关于子网的部份略过,等您对 named 有一定的经验了,随时欢迎回来再看,也很欢迎您 来信 和网中人讨论心得!


无论如何,我先得在 rh7.1 上面确定 /etc/named.conf 这个档案有关于‘父网’的设定::

zone "1.0.10.in-addr.arpa" IN {
type master;
file "10.0.1.rev";
};



事实上,上面的内容和我们以前的设定没什么不一样,您只需确定它有这个设定就行了。然而,原本的 /var/named/10.0.1.rev 却必须修改一下,使之变成如下内容:

$TTL 86400
$ORIGIN 1.0.10.in-addr.arpa.; 宣告当前网络(父网)反解
@ IN SOA rh71.siyongc.domain. root.rh71.siyongc.domain. (
2001111701 28800 14400 3600000 86400 )
IN NS rh71.siyongc.domain.

; 以 $GENERATE 的方式,建立 CNAME ,将查询转往子网:
$GENERATE 128-159 $ CNAME $.sub-128

; 将 128 这个子网授权出去:
sub-128 IN NS lp64.dmz.domain.



在这个特殊的“切割子网”例子中,其中最关键的设定是 CNAME 的设定,如果您没忘记我前面是如何解释 CNAME 的话,您会知道凡是查询 CNAME 左边的记录,就转到 CNAME 右边再查一次。这里,我们用 $GENERATE 的方式将 128-159 这段记录用 CNAME 转向 sub-128 这个子网查询。


Tips:事实上,这个子网名称在 DNS 系统里面可以随便定义,比方说,有些人喜欢用 mask bit 的数目来定义,那就可以写成 128-27 ;当然,如果您喜欢用 IP 范围来定义也可以:128-159 。如何定义没关系,只要不混乱就行。

因为 128 至 159 这段 IP 实际上是在子网 10.0.1.128 里面的范围(这段现已授权出去,但您不能在 ineternet 上面查询 203.30.35.128.134 这样的五组数字的 IP 格式),当人们要查询所有以 10.0.1 开头的 IP 的时候,都会先向 1.0.10.in-addr.arpa. 的 NS 查询,也就是目前这台机器;然后再透过 CNAME 将查询转向其子网络 sub-128.1.0.10.in-addr.arpa. 进行查询,直至找到 128 至 159 之间的 PTR 记录为止。


Tips:在 A 和 B class 的子网授权设定中,只要不超过 24bit mask 且使用完整 otec 的话,应该无需使用 CNAME,直接为下一个 otec 进行 NS 授权就行了。

在上例中的最后一行,我将 sub-128 这个自己定义的子网记录项,以 NS 授权给 “lp64.dmz.domain.”来负责。而至于 lp64.dmz.domain 的 IP 在哪里呢?那就透过正解查询来获得了,我们无需担心这个,除非解那边没设定起来。

接下来,让我们转到 sub-128.1.0.10.in-addr.arpa. 的 NS ,也就是 lp64 这台机器上面。首先,需要修改 /etc/named.conf 档案,让 named 知道 sub-128 目前由它来负责:

zone "1.0.10.in-addr.arpa" {
type forward;
forwarders { 192.168.100.23; };
};

zone "sub-128.1.0.10.in-addr.arpa" {
type master;
file "10.0.1.128.rev";
};



这里的 forwarder 之作用与前面介绍的 sub-zone 授权时的设定一样:如果您不能查询到父网的 NS 的话,您就没办法查询其它子网络。

当我们完成 named.conf 的设定之后,还必须在 /var/named 目录下面建立相应的档案,也就是 10.0.1.128.rev 这个档:

$TTL 86400
$ORIGIN sub-128.1.0.10.in-addr.arpa.; 关于当前子网的设定
@ IN SOA lp64.dmz.domain. root.lp64.dmz.domain. (
2001111701 28800 14400 3600000 86400 )

@ IN NS lp64.dmz.domain.; 这应该和父网指定的一致

; 固定 IP 的反解:
129 IN PTR dialser.dmz.domain.
130 IN PTR lp64.dmz.domain.
131 IN PTR rh71.dmz.domain.

; 拨接主机的反解:
$GENERATE 132-155 $ PTR dialup-pc$.dmz.domain.



在当前的 Internet 环境来说,能顺利申请到完整的一组 class IP 的情况实在非常少见了。这时候您很可能要需要上游 ISP 帮您做反解,要惊动他们是在所难免的。如果他们肯受权下来,那么您自己的设计弹性就比较高,日后要修改也容易得多。但如果上游没有受权的话,您可千万不要越俎代庖,设了也等于白设:因为您的 NS 并没有经过授权,别人是不能从 root zone 反查询得到的。而且,更严重的是:如果您自己将整个 C Class 的反解私自设定起来的话,由于没办法知道除了您这个 subent 之外的其它 subnet 的信息,也就没办法设定。这样结果将会是:如果您不设,或许可以透过 ISP 查询到它们;如果设了反而查不到!

但是,如果在上游没有授权的情况之下,您日后的每次修改,都必须要通知上游,才能保持数据的准确性,却是十分的不方便。下面的这个方法是是一个折衷的办法,您只需到上游注册一次(如果上游不同意,请努力说服他们),日后的变动则完全看您自己的意思了:

假设您是一个 ADSL 的用户,获得 5 个可用 IP,分别从 211.2.3.113 到 211.2.3.118;同时,您为您目前的 domain 注册为 my.domain。这样,您首先要到上游完成反解的注册,这样设就可以了:

$ORIGIN 3.2.211.in-addr.arpa.
......
114INCNAME114.my.domain.
115INCNAME115.my.domain.
116INCNAME116.my.domain.
117INCNAME117.my.domain.
118INCNAME118.my.domain.
......



然后您也无需另外设定反解,全部都在 my.domain 的记录文件上面设就可以了:

......
$ORIGIN my.domain.
114INPTRdns.my.domain.
dnsINA211.2.3.114
115INPTRwww.my.domain.
wwwINA211.2.3.115
116INPTRftp.my.domain.
ftpINA211.2.3.116
117INPTRpop.my.domain.
popINA211.2.3.117
118INPTRsmtp.my.domain.
smtpINA211.2.3.118
......



照这样看来应该没什么问题了。假如您对子网划分有不理解的地方,欢迎参考一篇我与网友的讨论信件 (注意:内容是引用旧版的文章,所以设定上和目前的方法有所不同,但原理还是一样的)。

许多人都觉得:我没有设定反解、ISP 那边也不愿意帮忙设定,我的 DNS 还不是照常工作!那么究竟什么时候才会用到反解呢?如果不设定反解有什么后果呢?嗯~~ 如果有这个疑问的话,我建议您先读读如下的文章,相信您就知道反解的重要性在哪里了:


reverse domain 的使用时机

另外,如果 DNS 授权有误,则很容易做成 lame server 的问题。发生这问题的原因是:从 DNS 系统上查询某一个名称的时候,获得一个 NS 信息,然后向那个 NS 进行查询的时候却得不到结果。您可以参考下面这篇文章认识问题产生的理论,然后进行修正:


DNS/bind-4.9.x Lame Server 讯息所代表的意义 ( 理论篇 )

不过,如果 lame server 是由于别人乱设而引起的话,那您只能设法与对方的管理原取得联系,然后请对方修改了。



关于 DNS 的安全问题

DNS 系统在网络沟通上面提供了非常便利的途径,一个设定完整的 DNS 系统,无论在管理或除错方面都是非常有效的。然而,在许多网络入侵案例中,往往因为 DNS 提供的信息过多,而让入侵者省却了许多步骤和时间,这也增加了对入侵行为的侦察和预警的难度。

所以,假如您同时需要为内部和外部网络提供 DNS 服务、而又有条件的话,最好设定多台 DNS 服务器,分别对内和对外提供服务。在所有这些对外服务的机器上,我们只设定最少的必须记录就可以了,千万不要把 HINFO 等一些关于主机和网络环境的记录写进去。同时,任何不必要对外提供的 IP 和主机记录,一概删除就是了。而其它的为信任网络提供服务的主机,则无论如何也不要让过多的 DNS 信息流出 internet。您甚至可以通过火墙过滤来保护内部的 DNS 服务查询。

为了获得更好的安全效果,您可以在 /etc/named.conf 档案中设定一些限制,让 DNS 仅对那些信任的网络或主机提供服务,或是挡掉来自不信任主机的查询。下面,我提供一个安全设定的范例给大家参考一下:

//---file: /etc/named.conf
//

//---首先定义各安全群组---//
acl LOCALHOST {
127.0.0.0/8;
};
acl DMZ_net {
10.0.1.128/27;
};
acl TRUSTED_net {
192.168.100.0/24;
192.168.2.0/24;
};
acl TRUSTED_host {
192.168.100.26/32;
10.0.1.130/32;
10.0.1.161/32;
};
acl BAD_Guys {
38.38.38.38;
44.44.44.44;
119.119.119.119;
}; //-注:以上 ip 仅作例子 :-)!-//

//---然后在 options 中设定预设原则---//
options {
directory "/var/named";

forward first;
forwarders {
139.175.10.20;
168.95.1.1;
};

allow-update { none; };
allow-transfer { none; };
allow-query { any; };
blackhole { BAD_Guys; };
};


//---在各区域中另行设定区属安全原则---//
zone "." {
type hint;
file "named.ca";
};

zone "localhost" IN {
type master;
file "localhost.zone";
};

zone "0.0.127.in-addr.arpa" IN {
type master;
file "named.local";

//--- 注:上两个 zone 原本有 update 限制的,
//--- 但由于已经在 options 中限制过了,故不重复。


zone "100.168.192.in-addr.arpa" {
type master;
file "192.168.100.rev";
allow-query { LOCALHOST; DMZ_net; TRUSTED_net; };
allow-transfer { TRUSTED_host; };
notify yes;
also-notify { 10.0.1.130; 192.168.100.26; };
};

zone "1.0.10.in-addr.arpa" {
type master;
file "10.0.1.rev";
allow-query { LOCALHOST; DMZ_net; TRUSTED_net; };
allow-transfer { TRUSTED_host; };
notify yes;
also-notify { 10.0.1.130; 10.0.1.161; };
};

zone "128.1.0.10.in-addr.arpa" {
type slave;
file "slave.10.0.1.128";
allow-query { LOCALHOST; DMZ_net; TRUSTED_net; };
};

zone "siyongc.domain" {
type master;
file "siyongc.domain";
allow-query { LOCALHOST; DMZ_net; TRUSTED_net; };
allow-transfer { TRUSTED_host; };
notify yes;
also-notify {
192.168.100.26;
10.0.1.130;
};
//--- 如果您有设定 dynamic dns 或是 samba 更新,请开放 update 。
allow-update { LOCALHOST; TRUSTED_net; };
};

zone "home.siyongc.domain" in {
type slave;
masters { 192.168.100.26; };
file "slave.home.siyongc.domain";
allow-query { LOCALHOST; DMZ_net; TRUSTED_net; };
};



在设定 DNS 的安全原则的时候,有些问题您必须注意:

如果 client (包括 localhost ) 如果不在 allow-query 范围内的话,将不能查询该区域的任何信息。


当这一个区域作为 master 且有其它 slave 指向它的时候,slave 主机必须同时被包括在 allow-query 和 allow-transfer 设定中才可以完成区域转移。


那些不在 allow-query 设定当中的主机,虽然不能够直接将 server 指向这台 DNS 来查询所在区域。然而,如果对方先将 server 指向另一台 DNS 主机,且该主机是属于 allow-query 设定之中的话,也可以对该区域进行查询。

例如,如果在 zone "siyongc.domain" 当中允许 DMZ_net 的查询。虽然从外面的主机不能直接查询这个 zone ,但只要对方将 server 指向 DMZ_net 其中任一台 DNS 主机,而该主机的 allow-query 可以让其通过的话,那他们也就可以查询 siyongc.domain 了。


实质上,also-notify 并不能限制区域转移的进行,它只不过可以让 master 通知其中的 slave 主机罢了。任何一台 DNS,只要通过了 allow-transfer 和 allow-query 检查,就可以用进行区域转移了。


关于 allow-update 的限制,并非是说在 slave 上允许 master 将数据同步过来,而是针对动态 DNS 协议所进行的限制。



一些注意之处

对于刚开始接触 DNS 的朋友来说,常常会“硬性的”将反解和正解联系起来。其实在实际的设定中是非常多样化的,反解和正解在许多情形下未必是一致对应的。比如我有一组 192.168.100.* 的 C Class IP ,我并非只能分配给 siyongc.domain 这一个 zone 。如果我喜欢,可以将里面的 IP 分配给好几个 zone 来使用。同理,我的 siyongc.domain 下面,也未必只能用 192.168.0.* 里面的 IP,事实上我还可以使用其它的 IP 。很简单一个例子是:我的 rh71 这台主机,就有三张路卡,它们分别属于不同的 IP 网络,但它们可以使用同一个主机名称,也就是说,您可以为同一个 RR 记录名称设定多个 A 记录。

如果您机器有多个名称的话,那么,在反解那里也容许一个 IP 有多个 PTR 记录的。不过,如果您用 nslookup 的正常模式查询的话,会以 roung robind 的形式一次显示一个记录,您要经过 set type=ptr 之后才可以看到全部记录。

每次当您修改了 master 机器上的的内容,请一定要更新 Serial 号码!同时,在 slave 上面设定的时候,也不要漏了 masters 的 s 字母;同样,设定 forwarder 的时候,最后也有一个 s 字母~~


如果您要修改 NS 或 MX 这些敏感性记录(例如移机或更换 IP ),事先请将 TTL 降低,然后等上一个 TTL 过期之后再修改,并且利用外面的 DNS 来查询修改结果。等稳定之后才将 TTL 提高到原来水平。如果记录数据都很稳定,不妨将 TTL 提高一点,这对于繁忙的系统有所帮助,但对于修改则非常不便。所以,如何拿捏 TTL 的水平,也是非常考究的。

老实说,我自己对 DNS 的设定也是一知半解而已。如果您想看一看正规的设定范例,可以到
http://dnsrd.nctu.edu.tw/Named-Conf/conf.html 看看;
DNS 的技术原理则可以参考:
http://turtle.ee.ncku.edu.tw/~tung/dns/
另外,
http://www.tp.edu.tw/service/dns0.htm
这篇相当容易上手,也建议看看。最后,这个
http://www.acmebw.com/cats.htm
网站,也有许多 DNS 的问题与解答,有问题可以到那里找找,或许答案早在那里了!还有,到
http://www.isc.org/products/BIND/
这个网站,您可以了解到最新最全面的关于 BIND 这个软件的信息。

如果您非常正经的想学习一下 DNS ,有一本 O'reilly 出版的书是非看不可的,那本书叫 ‘ DNS & Bind ’。您最好找最新版的回来看,听说已经有第 4 版了。


转载自linuxd

为什么rh9.0下的dns一开,53端口开,953为什么也要开啊?

>(奇怪,目前的 DNS 还有其它 class 吗?)。

应该有三种类型。(参看unix管理员手册)

>> Sendmail 与 MX
在哪里有?

好东西值得收藏,我还没有仔细看呢。所以暂时还没有问题!

Re: [转贴]bind9配置精讲(二万字)

发表于 : 2009-10-30 9:07
guiwen1158
:em06