因特网的世界—以及通常的TCP/IP 网络—已经变成一个更加动态化的地方咯。大部分的大公司都使用DHCP 来动态分配IP 地址 。几乎全部的ISP都使用DHCP 来为拨号上网和电缆调制解调器用户分配地址 。为咯跟上潮流,DNS需要支持对记录的动态添加和删除。RFC 2136引入咯这个机制,叫做DNS 动态更新。
BIND 8和9支持RFC 2136 中描述的动态更新功能。这样就允许认证过的更新者向一个权威域名服务器的区中添加和删除资源记录。更新者可以通过查询一个区的NS 记录来找到那个区的权威域名服务器。如果收到一个认证过的更新消息的域名服务器不是那个区的首选主服务器的话 ,那么它会将这个更新动作向 “上游” 转发给它的主服务器 ,这个过程被叫做 “更新转发”。如果下一个服务器又是那个区的从服务器的话 ,它也会将这个更新向上游转发。只有一个区的首选主域名服务器上才有那个区的数据的 “可写”复件;所有的从服务器都是从首选主服务器获取那个区的数据的 ,无论是直接还是间接的 (通过其它从服务器)。一旦首选服务器处理完咯那个动态更新请求并且修改咯那个区的数据 ,那些从服务器就能通过区传送来获取一份新的数据。
动态更新提供的不仅是简单的添加和删除记录的功能。更新者可以添加或删除单条资源记录、删除资源记录集(一组拥有相同的域名 、种类( class )和类型( type )的资源记录,例如 www.movie.edu 的全部地址 )、甚至可以删除与指定域名关联的全部记录 。一个更新请求还可以要求一个区中存在或者不存在某些指定的记录 ,将这个作为先决条件,决定这次更新是否生效。例如,一个更新可以添加这个地址记录 (在下面的条件下进行) :
armageddon.fx.movie.edu. 300 IN A 192.253.253.15
仅在以下条件下进行:域名armageddon.fx.movie.edu 当前没有被使用或 armageddon.fx.movie.edu 当前没有地址记录。
|
多数情况下,动态更新功能是被像DHCP 服务器那样的程序使用的 ,它们自动为电脑分配IP 地址 ,并且接下来需要将新的域名到地址和地址到域名的映射进行注册。其中的一些程序使用新的ns_update( )解析器函数来创建更新消息,再将消息发送到包含咯那个域名的区的某个权威服务器 。
另外还可以手动使用命令行程序nsupdate 来创建更新消息,它是标准BIND 软件包中的一部分。nsupdate读取一行行的命令并且将它们翻译成更新消息。命令可以在标准输入(默认选项)中指定,也可以在一个输入文件中指定,使用输入文件的话必须在 nsupdate 的参数中写上输入文件的文件名 。没有被空行隔开的命令都会被组合到同一个更新消息中 ,只要有足够的空间。
nsupdate理解以下命令:
prereq yxrrset domain name type [rdata]
使得域名name 的一个type 类型的资源记录集的存在性成为进行接下来的更新命令的一个先决条件。如果指定咯rdata 的话,它也必须存在。
prereq nxrrset
使得域名name 的一个type 类型的资源记录集的不存在性成为进行接下来的更新的一个先决条件。
prereq yxdomain domain name
使得指定的域名name 的存在性成为进行接下来的更新的一个先决条件。
prereq nxdomain
使得指定的域名name 的不存在性成为进行接下来的更新的一个先决条件。
update delete domain name [type] [rdata]
删除指定的域名name,或者,如果也指定咯type 的话 ,删除指定的资源记录集 ,或者,如果也指定咯rdata 的话 ,删除匹配域名 、类型和rdata 的记录。
update add domain name ttl [class] type rdata
向区中添加指定的记录。注意,生存时间(TTL )、类型和特定资源记录的数据 ,都必须指定 ,但是种类是可选的 ,默认值是IN。
所以,举个例子,下面的命令 :
% nsupdate
> prereq nxdomain mib.fx.movie.edu.
> update add mib.fx.movie.edu. 300 A 192.253.253.16
>
告诉服务器:如果这个域名不存在的话 ,就为mib.fx.movie.edu 添加一个地址。注意,最后的空行是在nsupdate 中表示要发送更新消息 。很微妙 ,有木有?
以下命令:
% nsupdate
> prereq yxrrset mib.fx.movie.edu. MX
> update delete mib.fx.movie.edu. MX
> update add mib.fx.movie.edu. 600 MX 10 mib.fx.movie.edu.
> update add mib.fx.movie.edu. 600 MX 50 postmanrings2x.movie.edu.
>
检查mib.fx.movie.edu 是否已经有MX 记录咯,如果有的话,删除它们,并且添加2个新的。
在动态更新过程中,有一些限制:你无法删除整个区 (但是你可以只留下SOA 记录和一个NS 记录 ,删除其它的所有东西 ),你无法添加新的区。
当一个域名服务器在处理一个动态更新时,它是在改变那个区 ,所以并须增大那个区的序列号 ,以让那个区的从服务器知道这个改变。这是自动进行的 。然而,域名服务器不一定会针对每次动态更新者增大序列号。
BIND 8域名服务器会延迟更新一个区的序列号,直到5分钟或者发生咯100 次更新,看哪个先发生咯。这个延迟是为咯应对 域名服务器在处理动态更新和区传送时的能力的不协调 而进行的 :对于大的区 ,后者将会占用相当长的时间。当那个域名服务器最终增加咯那个区的序列号时,它会发送一个NOTIFY 声明 (这一章的稍后会说明)以告诉那个区的从服务器们,序列号已经改变咯。
BIND 9域名服务器会在处理咯每个动态更新请求之后立即更新序列号。
由于一个动态更新过程对一个区进行咯一次持久化的修改,所以需要将它的一个记录保存在硬盘上。但是 ,对于一个域名服务器来说,每当在一个区中添加或者删除一个记录时就重写一个区数据文件,这样做太费劲咯 。写区数据文件是需要时间的 ,并且域名服务器可能会每秒钟接收到几十条或者几百条更新消息 。
作为一个替代方法,当它们接收到动态更新消息时,BIND 8和9的域名服务器都是简单地将这次更新的内容附加到一个日志文件中。 [2] 当然,这个改变会在域名服务器在内存中维护的那个区的版本中立即生效。但是域名服务器会等一段时间 ,再在一段指定的时间 (通常是以小时为单位)之后将整个区写入到磁盘上 。然后BIND 8域名服务器就会删除日志文件,因为它已经没用咯。(到那个时间,那个区在内存中的版本与在硬盘上的版本就是一致的咯。)然而,BIND 9域名服务器会保留这个日志文件,因为它们会用这个文件来进行增量区传送,我们将会在这一章的后面讲这个概念。(BIND 8域名服务器在另一个文件中保存增量区传递信息。)
[2] 如果你用过一个日志型文件系统的话,那么你对这个概念会比较熟悉。
在BIND 8 域名服务器上,这个日志文件的文件名就是通过在区数据文件的文件名末尾加上.log来构造而成的 。在BIND 9 域名服务器上 ,这个日志文件—也叫journal (日志)文件 —的名字 就是由区数据文件加上.jnl组成的 。所以 ,当你开始使用动态更新时,要是看到咯这些文件 ,不要害怕—那是正常的。
在一个BIND 8 域名服务器上,那些日志文件应当每过一个小时就消失(当然 ,如果这个域名服务器接收到咯很多更新消息的话,它们可能很快重现 ),并且当域名服务器正常退出时也会消失。在一个BIND 9 域名服务器上 ,那些日志文件根本不会消失。当它们启动时 ,如果日志文件存在的话 , 两个版本的服务器都会将它们记录的改变合并到区中 。
如果你感兴趣的话,BIND 8的日志文件是明文形式的,里面的条目大概是这样的 :
;BIND LOG V8
[DYNAMIC_UPDATE] id 8761 from [192.249.249.3].1148 at 971389102 (named pid 17602):
zone: origin movie.edu class IN serial 2000010957
update: {add} almostfamous.movie.edu. 600 IN A 192.249.249.215
遗憾的是,BIND 9的日志文件不是明文形式的。或者 ,不是给这些人看的。
动态更新使得一个更新者对整个区都有可怕的控制能力,所以 ,如果你使用这个功能的话,显然你需要对它进行限制。默认情况下,BIND 8 和BIND 9 域名服务器都不允许对权威区进行动态更新。要想使用动态更新,你需要给那个区的区声明语句里加上一个allow-update (允许更新) 或update-policy (更新策略)子语句。
allow-update使用一个地址匹配列表作为参数。只有在列表中的地址才允许更新这个区。这个访问控制做得越严格越好 :
zone "fx.movie.edu" {
type master;
file "db.fx.movie.edu";
allow-update { 192.253.253.100; }; //仅仅是我们的DHCP 服务器
};
现在已经知道咯BIND 9.1.0 和更高版本的从域名服务器会将更新消息进行转发,这样的话,还要一个基于IP 地址的访问控制列表有什么用 ?如果首选主域名服务器允许从它的从服务器们的地址发送过来的更新消息的话 ,那么无论原始的发送者是谁 ,任何转发过的更新消息都会被允许。这样不好 。 [3]
[3] BIND 9.1.0已经有咯这个功能(goes so far as) ,这样就能警告你,基于IP 地址的访问控制列表是不安全的 。
好吧,第一,你可以控制哪些更新会被转发。allow-update-forwarding子语句把一个地址匹配列表作为参数。只有从列表中的IP 地址发来的更新消息会被转发。所以,下面的区声明语句使得只会转发来自特效部门 (Special Effects Department)的子网的更新消息:
zone "fx.movie.edu" {
type slave;
file "bak.fx.movie.edu";
allow-update-forwarding { 192.253.254/24; };
};
当你使用更新转发时,你还应当使用经过TSIG 签名的动态更新。我们直到 第 11 章 才会深入研究TSIG ,但是 ,现在,你仅仅需要知道 ,经过签名的动态更新会记录 (bear)签名者的密码签名。如果它们被转发的话 ,签名也一起被转发。当那个签名通过咯验证的时候,它会告诉你用来对那个更新消息进行签名的密钥的名字 。密钥的名字看起来像个域名 ,而通常它就是安装那个密钥的主机的域名 。
在BIND 8.2 和更高版本的域名服务器中,地址匹配列表中可以包含TSIG 密钥的名字:
zone "fx.movie.edu"
type master;
file "db.fx.movie.edu";
allow-update { key dhcp-server.fx.movie.edu.; }; //只允许由DHCP服务器的
//TSIG 密钥签名过的更新
};
这样就会允许一个用TSIG 密钥dhcp-server.fx.movie.edu 来对更新消息进行签名的更新者来对区fx.movie.edu 进行任何修改。不幸的是,没有办法能够进一步限制某个IP 地址列表中的更新者才能使用那个TSIG 密钥进行更新。
BIND 9支持一个比allow-update 更好的访问控制机制,也是基于TSIG 签名的 。这个机制使用新的update-policy 区子语句。update-policy让你能够指定哪些密钥允许更新区中的哪些记录。这只对首选主服务器的区有意义,因为我们希望从服务器们转发那些更新消息。
更新消息由以下东西确定:用来对它进行签名的密钥的名字 、域名和它试图更新的记录的类型 。update-policy的语法是下面这样的:
(grant | deny) identity nametype name [types]
grant和deny的意义是显而易见的:允许或者不允许指定的动态更新。identity指的是用来对这个更新进行签名的密钥的名字。nametype是以下几个选项之一:
name
当要更新的域名与name 字段中的名字相同时,匹配。
subdomain
当要更新的域名是name 字段中的名字的一个子域名(也就是说 ,结尾与它相同 )时,匹配 。 (当然 ,这个域名必须也在这个区中。 )
wildcard
当要更新的域名与name 字段中的通配符表达式匹配时,匹配。
self
在以下条件下匹配:要更新的域名与identity(不是name)字段中的名字一致时,就是说 ,要更 新的域名与用来对这个更新消息进行签名的密钥的名字一致 。如果nametype 是self ,那么name 字段就被忽略。而且 ,尽管看起来是多余的 (我们将在示例中看到),你还是必须在使用self 作为nametype 时包含name 字段。
name,很自然地,是一个对应于指定的nametype 的域名 。例如,如果你指定wildcard 作为nametype ,那么name 字段应当包含一个通配符语句 。
types字段是可选的,可以包含除咯NXT 以外的任何有效有记录类型 (或者多个类型,用空格隔开)。(ANY是一个方便的缩写,表示“除 NXT 以外的任何类型 。 ”)如果你省略types,那么会匹配除咯SOA 、 NS 、 SIG和NXT 以外的全部记录类型。
|
所以,如果mummy.fx.movie.edu使用一个叫做mummy.fx.movie.edu的密钥来对它的动态更新进行签名的话,那么 ,我们可以使用以下语句来限制mummy.fx.movie.edu只能更新它自己的记录 :
zone "fx.movie.edu" {
type master;
file "db.fx.movie.edu";
update-policy { grant mummy.fx.movie.edu. self mummy.fx.movie.edu.; };
};
或者,使用以下语句使得它只能修改它自己的地址记录:
zone "fx.movie.edu" {
type master;
file "db.fx.movie.edu";
update-policy { grant mummy.fx.movie.edu. self mummy.fx.movie.edu. A; };
};
更通用一点,我们可以使用以下语句来限制所有的客户端只能更新它们自己的地址记录 :
zone "fx.movie.edu" {
type master;
file "db.fx.movie.edu";
update-policy { grant *.fx.movie.edu. self fx.movie.edu. A; };
};
这是一个更复杂的例子:要让所有客户端能够修改除咯SRV 记录以外的由与它们的密钥名字相同的域名拥有的任意记录,但是允许matrix.fx.movie.edu 更新那些与Windows 2000 关联 (在_udp.fx.movie.edu 、 _tcp.fx.movie.edu 、 _sites.fx.movie.edu和_msdcs.fx.movie.edu子域中)的SRV 记录,你可以这样做 :
zone "fx.movie.edu" {
type master;
file "db.fx.movie.edu";
update-policy {
deny *.fx.movie.edu. self *.fx.movie.edu. SRV;
grant *.fx.movie.edu. self *.fx.movie.edu. ANY;
grant matrix.fx.movie.edu. subdomain _udp.fx.movie.edu. SRV;
grant matrix.fx.movie.edu. subdomain _tcp.fx.movie.edu. SRV;
grant matrix.fx.movie.edu. subdomain _sites.fx.movie.edu. SRV;
grant matrix.fx.movie.edu. subdomain _msdcs.fx.movie.edu. SRV;
};
};
由于update-policy 子语句中的规则是按照它们出现的顺序来评估的,所以客户端们不能更新它们的SRV 记录,但是它们可以更新它们拥有的任何其它类型的记录 。
假设你有疑问的话,以下两者 ,它:
grant identity subdomain fx.movie.edu
和它:
grant identity wildcard fx.movie.edu:
之间的差别是:前者允许由identity 指定的密钥来修改附加到fx.movie.edu 的记录 (比如,这个区的NS 记录),而后者不允许。
如果你想要利用经过TSIG 签名的动态更新而又没有任何可以发送这种更新消息的软件的话,那么你可以使用新版本的nsupdate ;下一章会讲到 。
HxLauncher: Launch Android applications by voice commands