谈 DNS 解析工作原理并给自己的域名搭建 DNS 服务器

现在几乎所有的互联网主机都要使用到 DNS (Domain Name Server,域名系统) 。这篇文章就通过搭建自己的 DNS 服务器的方法学习 DNS 知识。

DNS 递归解析的工作原理

DNS 的解析是递归进行的,它的结构就像 Unix 目录结构一样:

DNS 解析结构
DNS 解析是颠倒的树状结构

如何理解?DNS 解析从顶端(Root)开始,向根域名服务器询问第一个区域的DNS(asia.),然后向 asia. 的 DNS 查询 goodspeed.asia. 的 DNS 以此类推。

你可能已经注意到了,这里我的域名后面加了一个“.”。这是完全合格域名(FQDN)的表示方法,用来指向 DNS 树状图中的一个确切位置。在上面的树状图中是这样表示的(设想我们要得是最下面的 ftp 节点):ftp -> openbsd -> org。把箭头用“.”替代再加上一个“.”用来表示根域名就变成了我们要的 FQDN。

现在你已经了解了 DNS 递归解析的基本工作原理,下面是 DNS 请求根服务器、Asia 的 DNS 和我自建的 DNS 的查询结果(留意 SECTION 中使用的 FQDN)。

goodspeed@Goodspeed-PC ~$ dig asia @k.root-servers.net

; <<>> DiG 9.18.6 <<>> asia @k.root-servers.net
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 5846
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 6, ADDITIONAL: 13
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;asia. IN A

;; AUTHORITY SECTION:
asia. 172800 IN NS a0.asia.afilias-nst.info.
asia. 172800 IN NS a2.asia.afilias-nst.info.
asia. 172800 IN NS b0.asia.afilias-nst.asia.
asia. 172800 IN NS b2.asia.afilias-nst.org.
asia. 172800 IN NS c0.asia.afilias-nst.info.
asia. 172800 IN NS d0.asia.afilias-nst.asia.

;; ADDITIONAL SECTION:
b0.asia.afilias-nst.asia. 172800 IN A 199.254.28.1
b0.asia.afilias-nst.asia. 172800 IN AAAA 2001:500:16::1
d0.asia.afilias-nst.asia. 172800 IN A 199.254.30.1
d0.asia.afilias-nst.asia. 172800 IN AAAA 2001:500:18::1
a0.asia.afilias-nst.info. 172800 IN A 199.19.55.1
a0.asia.afilias-nst.info. 172800 IN AAAA 2001:500:d::1
a2.asia.afilias-nst.info. 172800 IN A 199.249.114.1
a2.asia.afilias-nst.info. 172800 IN AAAA 2001:500:42::1
b2.asia.afilias-nst.org. 172800 IN A 199.249.122.1
b2.asia.afilias-nst.org. 172800 IN AAAA 2001:500:4a::1
c0.asia.afilias-nst.info. 172800 IN A 199.254.29.1
c0.asia.afilias-nst.info. 172800 IN AAAA 2001:500:17::1

;; Query time: 50 msec
;; SERVER: 193.0.14.129#53(k.root-servers.net) (UDP)
;; WHEN: Thu Aug 25 11:20:14 CST 2022
;; MSG SIZE rcvd: 503

goodspeed@Goodspeed-PC ~$ dig goodspeed.asia @a0.asia.afilias-nst.info

; <<>> DiG 9.18.6 <<>> goodspeed.asia @a0.asia.afilias-nst.info
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 21860
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 2, ADDITIONAL: 3
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;goodspeed.asia. IN A

;; AUTHORITY SECTION:
goodspeed.asia. 86400 IN NS sns.goodspeed.asia.
goodspeed.asia. 86400 IN NS ns.goodspeed.asia.

;; ADDITIONAL SECTION:
ns.goodspeed.asia. 86400 IN A 209.141.50.232
sns.goodspeed.asia. 86400 IN A 209.141.50.232

;; Query time: 130 msec
;; SERVER: 199.19.55.1#53(a0.asia.afilias-nst.info) (UDP)
;; WHEN: Thu Aug 25 11:20:37 CST 2022
;; MSG SIZE rcvd: 110

goodspeed@Goodspeed-PC ~$ dig goodspeed.asia @ns.goodspeed.asia

; <<>> DiG 9.18.6 <<>> goodspeed.asia @ns.goodspeed.asia
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 12775
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: 09b3c4ba0ca7cc7d010000006306eaf8bf6bf449204efd0b (good)
;; QUESTION SECTION:
;goodspeed.asia.			IN	A

;; ANSWER SECTION:
goodspeed.asia.		10800	IN	A	209.141.50.232

;; Query time: 180 msec
;; SERVER: 209.141.50.232#53(ns.goodspeed.asia) (UDP)
;; WHEN: Thu Aug 25 11:22:32 CST 2022
;; MSG SIZE  rcvd: 87

递归解析 DNS 与权威 DNS 服务器

你可能觉得上面讨论的 DNS 服务器很陌生,这是因为 DNS 中存在着两种类型的服务器。递归解析服务器是帮你进行递归解析并缓存的服务器。权威服务器是真正储存记录的服务器。举例:114.114.114.114 是递归解析服务器,193.0.14.129 (k.root-servers.net)  是权威服务器。

goodspeed@Goodspeed-PC ~$ nslookup goodspeed.asia
Server:		192.168.1.104
Address:	192.168.1.104#53

Non-authoritative answer:
Name:	goodspeed.asia
Address: 209.141.50.232

这里 nslookup 在应答上方加上 Non-authoritative answer(非权威解答)就是因为 DNS 查询是由 192.168.1.104 完成的,而它不是 goodspeed.asia. 的权威服务器。

搭建自己的权威服务器

注意,搭建之前务必在测试域名下,不然出错了以后可能会很麻烦。这里我使用的操作系统是 OpenBSD,如果你使用的别的操作系统记得留意配置文件的路径。

BINDBerkeley Internet Name Domain)是现今互联网上最常使用的DNS软件,使用BIND作为服务器软件的DNS服务器约占所有DNS服务器的九成。BIND现在由互联网系统协会(Internet Systems Consortium)负责开发与维护。来自 Wikipedia。

安装 ISC BIND (named)  :

# pkg_add isc_bind

编写 named 的配置文件:

options {
	directory       "/";

	recursion no;
	allow-transfer { none; };

	auth-nxdomain no;

	listen-on { any; };
	listen-on-v6 { any; };
};

zone "goodspeed.asia" {
    type	master;
    file	"master/db.goodspeed.asia";
};

因为这是权威服务器,所以者里用 recursion no 把递归解析关闭了。下面的 zone 改为你想管理的区域(域名),file 的命名随意。

下面是 master/db.goodspeed.asia 的内容,里面记录的意义一会解释:

$TTL 10800

@ IN SOA ns.goodspeed.asia. nios34.disroot.org. (
        2022082503
        86400
        7200
        3600000
        3600 )

        IN NS   ns.goodspeed.asia.
        IN A    209.141.50.232

sns     IN A    209.141.50.232
ns      IN A    209.141.50.232
www     IN A    209.141.50.232

第一个参数是名称,里面的 @ 表示当前的区域,当留空时表示使用上一条记录的名称。IN 前的位置表示的是 TTL (以秒记),如果缺省则表示使用默认的(第一行)的 TTL。IN 表示的是 Internet,然后是记录类型和记录信息。

SOA(Start Of Authority)记录与 NS  记录

Start Of Authority(缩写为 SOA 记录)是域名系统 (DNS) 中的一种资源记录,包含有关区域的管理信息。对照着上面的配置文件看,ns.hackflow.org. 表示这台 DNS 服务器,nios34.disroot.org. 表示电邮地址。

nios34.disroot.org. 会被理解为 nios34@disroot.org,如果电邮地址中有“.”则需要反斜杠进行转义。

后面括号里的是这些信息(都以秒为单位):序列号、刷新时间(上级查询 SOA 记录的间隔,推荐 86400 [24h])、重试时间(服务器无响应时重新请求 SOA 记录的间隔,必须小于刷新时间,推荐 7200 [2h])、到期时间(服务器无响应时停止继续请求的时间,必须大于前两者之和,推荐 3600000 [1000h])、最小值(负缓存的存活时间,使用 3600)。

其中序列号再每次修改后需要自增,推荐的格式是 YYYYMMDDNN,前四位表示年份然后是两位月、两位日、两位修订号。比如 2022082503 是 2022 年 8 月 25 日第三次修订。

NS 记录用来指示其对应的权威 DNS 服务器,这里需要指向这台服务器的域名。

另外,需要建立两条关于这台服务器(ns.x.y 和 sns.x.y)的 A 记录,指向自己的 IP。

检查配置文件并执行

先使用 named-checkconf 检查 named 配置文件:

# named-checkconf /var/named/etc/named.conf

然后使用 named-checkzone 检查区域文件:

named-checkzone goodspeed.asia /var/named/master/db.goodspeed.asia

运行!

rcctl enable isc_named && rcctl start isc_named

DNS Host/DNS 注册

如果像我一样把 DNS 服务器架设在要管理域名的下面就需要进行 DNS 注册。入口应该在你的域名注册商那里,下面是腾讯云的截图:

腾讯云的 DNS Host 设置界面
腾讯云的 DNS Host 设置界面

然后就可以设置域名的 DNS 服务器了。这里的原理实际上就是把 IP 添加到上级 DNS 服务器,具体可见上面查询中的 ADDITIONAL  SECTION。

调试建议

named 默认会把日志输出到 syslog,在 OpenBSD 中对应 /var/log/messages。

dig 可以用来执行 DNS 请求,Arch 系中的包名为 bind。在后面加 @x.x.x.x 可以指定要查询的 DNS 服务器。第一个参数是要请求的记录类型,缺省为 A 记录。

$ dig goodspeed.asia
...
$ dig SOA goodspeed.asia @ns.goodspeed.asia
...
$ dig NS goodspeed.asia
...