DNS动态更新

  • 什么是DNS动态更新
  • DNS动态更新与BIND软件的关系
  • 如何使用DNS动态更新
  • bind9环境nsupdate工具动态更新权威区数据举例
  • nsupdate入门
  • nsupdate使用细节
  • 实现基于TSIG的DNS动态更新


什么是DNS动态更新

RFC 2136描述了这样一种机制:它允许通过授权的更新者updater对权威DNS服务器的区数据动态的增加、删除资源记录。它给DNS系统日常运维带来了一种更加方便的变更区数据手段,管理员不再通过手工修改配置文件的方式变更数据。同时,它也提供了DHCP服务器分配IP地址后可通过DNS动态更新的机制自动在DNS权威区中添加IP与域名的对应记录(DDNS)的手段。

DNS动态更新与BIND软件的关系

BIND8和BIND9都支持RFC 2136所描述的DNS动态更新功能,但不是BIND软件独有,Windows Server作为DNS服务器时也是支持这个机制的。

如何使用DNS动态更新

  1. 一些程序内部已经具备此功能的函数调用,例如dhcpd这个软件它会通过ns_update()创建更新消息。
  2. 命令行工具nsupdate(此程序已经包含在BIND软件包中,安装后在bin目录下)可实现手动通过nsupdate命令创建更新消息,这个在DNS系统运维的时候比较常用。在对DNS系统的二次开发时可调用包装这个工具。

bind9环境nsupdate工具动态更新权威区数据举例

nsupdate入门

nsupdate工具是一个交互式的命令工具,在服务器上执行nsupdate然后Enter进入,先尝试一下如下:

[root@localhost ~]# nsupdate
> server 127.0.0.1
> update add xxx.test.com 300 A 3.3.3.3
> send
update failed: REFUSED
>quit

上面执行结果显然是失败了,但通过这些命令我们可以看到大概使用的思路:通过server制定DNS服务器的IP地址、通过update add命令向test.com区新增一个域名xxx.test.com、通过send命令提交、通过quit命令退出。
当然,这个失败的原因是named.conf文件中没有开启update,需要在对应的区配置部分显示的配置allow-update语句,简单的举例如下:

zone "test.com" {
	type master;
	allow-update { any; };
	file "test.com.zone";
};

重新测试一遍上面失败的nsupdate命令,没有报错。

[root@localhost ~]# nsupdate 
> server 127.0.0.1
> update add xxx.test.com 300 A 3.3.3.3
> send
> quit

bind的相关日志打印如下:
19-Jun-2020 22:09:51.370 update: info: client @0x7f22a400a2b0 127.0.0.1#26718: updating zone 'test.com/IN': adding an RR at 'xxx.test.com' A 3.3.3.3 使用dig命令测试解析正常。

[root@localhost bind]# dig @192.168.3.160 xxx.test.com +short
3.3.3.3

查看test.com.zone文件内容发现没有这个xxx.test.com域名。

[root@localhost run]# cat test.com.zone
$TTL 3h

@	IN SOA dns1.test.com. manager.test.com. (
		1	;Serial
		3h	;Refresh after 3 hours
		1h	;Retry after 1 hour
		1w	;Expire after 1 week
		1h)	;Negative caching TTL of 1 hour
;
@	IN NS dns1.test.com.
@	IN NS dns2.test.com.

;server domain
;
dns1	3600	IN	A	111.10.10.10
dns2	3600	IN	A	111.10.10.20
www	300 	IN	A	101.10.10.10
hello	20  	IN	A	101.10.10.20
a	20  	IN	CNAME	hello
mail	300 	IN	A	101.10.10.30
time		IN 	A	2.2.2.2

而存放zone文件的目录下多了一个test.com.zone.jnl 的文件,文件内容是乱码,无法查看。
综上,nsupdate的入门使用貌似不难,但有一些现象和配置我们还是没有根本了解,下面我们就来详细的说说这些细节。

nsupdate使用细节
  • 关于jnl文件的细节
    动态更新的区变化会保持在jnl文件中,此文件是二进制格式,不能手动编辑。更新的数据会定期的从jnl文件转存到zone文件中,但这个转存不是更新后立即执行,因为如果是立即执行那么一个大的区在频繁更新时候会导致服务器变动很慢。经测试,bind9这个转存的默认时间是15分钟,转存过程中可能还能临时看到jnw和jbk文件,但这些都不需要我们关注。
    在上面的test.com例子中,如果我们希望将目前jnl文件中的数据先转存到zone文件中,可以执行rndc sync test.com命令,此时会立即转存。
    - 转存后zone文件的格式会变
    动态更新成功且jnl配置转存成功后,我们再查看原来的zone文件会发现文件的内容格式变了,貌似给我们大扫除了一遍。真是让人激动,上面test.com的例子中转存后的zone文件内容如下,大家可自己对比看看。
[root@localhost run]# cat test.com.zone
$ORIGIN .
$TTL 10800	; 3 hours
test.com		IN SOA	dns1.test.com. manager.test.com. (
   			3          ; serial
   			10800      ; refresh (3 hours)
   			3600       ; retry (1 hour)
   			604800     ; expire (1 week)
   			3600       ; minimum (1 hour)
   			)
   		NS	dns1.test.com.
   		NS	dns2.test.com.
$TTL 3600	; 1 hour
   		MX	10 mail.test.com.
$ORIGIN test.com.
$TTL 20	; 20 seconds
a			CNAME	hello
$TTL 50	; 50 seconds
b			A	1.1.1.1
$TTL 3600	; 1 hour
dns1			A	111.10.10.10
dns2			A	111.10.10.20
$TTL 20	; 20 seconds
hello			A	101.10.10.20
$TTL 300	; 5 minutes
mail			A	101.10.10.30
$TTL 10800	; 3 hours
time			A	2.2.2.2
$TTL 300	; 5 minutes
www			A	101.10.10.10
xxx			A	3.3.3.3

- nsupdate命令参考
nsupdate命令有很多,它还具备判断类命令,例如先判断这个要添加的域名是不是存在,如果不存在则添加。

命令

功能介绍

prereq nxdomain domain name

执行更新前,必须满足指定的domain name不存在

prereq yxdomain domain name

执行更新前,指定的domain name必须存在

prereq nxrrset domain name type

执行更新前,指定的domain name的type类型的记录(RRset)必须不存在

prereq yxrrset domain name type [rdata]

执行更新前,指定的domain name的type类型的记录(RRset)必须存在,如果指定了rdata,那么也必须存在。

update add domain name ttl [class] type rdata

在区域中增加指定的记录,处理type和rdata之外还必须包含ttl,class类是可选的默认是IN

update delete domain name [type] [rdata]

删除指定的域名,例如update delete test.com MX

实现基于TSIG的DNS动态更新

上面test.com区数据动态更新举例时配置文件有allow-update { any; };这个配置,这any肯定是不安全的。虽然allow-update这里也可以添加基于IP的ACL来实现动态更新源地址的控制,但还是不够安全,因为这种基于UDP的更新很容易伪装源IP造成系统风险。所以BIND建议通过事物签名(TSIG)来加密和认证所进行的更新。举例说明如下。
首先,bind安装完毕后,在sbin目录下有tsig-keygen命令,通过这个命令对一个密钥名称进行计算得到共享密钥,如下:

[root@localhost sbin]# ./tsig-keygen --help
tsig-keygen: invalid argument --
Usage:
 tsig-keygen [-a alg] [keyname]
  -a alg:        algorithm (default hmac-sha256)
[root@localhost sbin]# ./tsig-keygen -a hmac-md5 mytest > mytest.key
[root@localhost sbin]# cat mytest.key 
key "mytest" {
	algorithm hmac-md5;
	secret "7fDlWke7zAvqD+I6ubgXwA==";
};

将上面生成的密钥信息配置到named.conf文件中

key "mytest" {
	algorithm hmac-md5;
	secret "7fDlWke7zAvqD+I6ubgXwA==";
};
zone "test.com" {
	type master;
	allow-update { key mytest; };
	file "test.com.zone";
};

再使用nsupdate工具举例如下:

[root@localhost etc]# nsupdate -y mytest:7fDlWke7zAvqD+I6ubgXwA==
> server 127.0.0.1
> zone test.com
> update add xxx3.test.com 3000 A 6.6.6.6
> send
> quit
[root@localhost etc]# dig @192.168.3.160 xxx3.test.com
; <<>> DiG 9.11.4-P2-RedHat-9.11.4-16.P2.el7_8.6 <<>> @192.168.3.160 xxx3.test.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 37724
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;xxx3.test.com.			IN	A
;; ANSWER SECTION:
xxx3.test.com.		3000	IN	A	6.6.6.6

;; Query time: 0 msec
;; SERVER: 192.168.3.160#53(192.168.3.160)
;; WHEN: Fri Jun 19 23:13:34 EDT 2020
;; MSG SIZE  rcvd: 58

19-Jun-2020 23:13:16.323 update: info: client @0x7ff39000eef0 127.0.0.1#51058/key mytest: updating zone 'test.com/IN': adding an RR at 'xxx3.test.com' A 6.6.6.6 nsupdate工具实现DNS动态更新本文就介绍到这,实际系统运维过程中面对集群架构的DNS系统还是要涉及一些细节,这个我们后面再针对性的介绍。