DNS是如何解析主机名的

DNS 解析的作用就是将主机名转换为 IP 地址,那么 DNS 解析过程是怎么样的,DNS 服务器又是如何快速响应全球用户的请求的呢?

DNS 解析原理

在解释 DNS 解析原理前首先需要知道的是,DNS 服务器只是一种统称,实际上 DNS 服务器的不同类型负责完全不同的功能,这对于后续理解整个原理具有非常关键的作用。下面根据 DNS 服务器功能不同主要分为 4 种类型:

  • 根域名服务器:根域名服务器负责维护顶级域名(如 .com, .net, .org 等)对应的 TLD 域名服务器地址,即当客户端向其发送 DNS 解析请求时,根域名服务器会返回其顶级域名对应的 TLD 域名服务器地址。目前全球的根域名服务器的任播(Anycast)地址共有 13 个

  • TLD 域名服务器(顶级域名服务器):不同顶级域名由不同的托管商负责,在根域名服务器响应了 TLD 域名服务器后的域名后,用户可以在 TLD 域名服务器获取到定向到权威服务器的信息,比如返回 zzcoder.cn 所在的权威服务器域名

  • 权威服务器:权威服务器维护了特定顶级域名下的所有子域名(比如 zzcoder.cn)的 DNS 记录。比如用户在域名注册商(如 DNSPod)下注册 zzcoder.cn 实际上就是在权威服务器添加各类 DNS 记录(A 记录,CNAME 记录等等)

  • 递归解析器:递归解析器也称为 DNS 解析器。递归解析器作为客户端与 DNS 域名服务器的中间人,是面向客户端最近的一站,它负责接收客户端的 DNS 查询,并分别向根域名服务器,TLD 域名服务器,权威服务器发送解析请求,然后将最终的响应返回给客户端。常见的公开的 DNS 解析器有 Google 的 8.8.8.8, Cloudflare 的 1.1.1.1

    每个递归解析器都会内置 DNS 根域名服务器的 13 个 任播地址

假设我们的设备配置了 Google 的 8.8.8.8 DNS 解析器,当我们通过浏览器访问域名时,是怎么完成解析的呢?

  1. 用户在浏览器中输入 zzcoder.cn,将向 8.8.8.8 DNS 递归解析器发送解析请求
  2. DNS 解析器首先将顶级域名 .cn 向 DNS 根域名服务器请求解析返回其 TLD 域名服务器地址
  3. DNS 解析器继续向 .cn 的 TLD 域名服务器请求二级域名 zzcoder.cn 对应的权威服务器地址
  4. 最后 DNS 解析器根据权威服务器返回的 DNS 记录响应给浏览器完成解析

上面的过程可以用下面的图比较清晰的解释,1,8 是 DNS 解析器和浏览器的交互,2-7是 DNS 解析器和域名服务器交互,9-10是 浏览器和目标网站的交互

recursive-resolver

如果对于图观察的比较细的话可以发现 DNS 解析器和客户端的交互(1,8)与 DNS 解析器和域名服务器的交互(2-7)箭头颜色不相同,这是因为它们分别对应两种不同类型的查询:

  • 递归查询:在递归查询中,DNS 客户端要求 DNS 服务器(一般为 DNS 递归解析器)将使用所请求的 DNS 记录响应客户端,即 DNS 解析器不能返回低级别域名服务器的地址,必须返回其对应的 DNS 记录
  • 迭代查询:在迭代查询中,DNS 客户端只需要 DNS 服务器返回其能够给出的最佳应答。比如 DNS 客户端向根域名服务器查询 zzcoder.cn,由于根域名服务器不知道权威服务器地址,因此它只需返回 .cn 对应的 TLD 服务器给客户端即可,后续的请求将由 DNS 客户端迭代发起

在上面这个图中,浏览器(客户端)向 DNS 解析器(8.8.8.8)发起的就是递归查询,而 DNS 解析器(8.8.8.8)向域名服务器发起的就是迭代查询。因此这里要注意理解,DNS 递归解析器本身做的实际上是迭代查询

本地域名服务器(LDNS)也是经常被人提到的一个名词,实际上它是我们本地搭建的一个 DNS 解析器,然后在路由器或本机指向该 DNS 解析器替代 ISP 提供的 DNS 解析器或者公共 DNS 解析器。当然本地域名服务器不一定使用迭代查询,比如开源项目 smartdns 只是对 DNS 解析请求做了转发

DNS 缓存

在上面已经把 DNS 解析的核心流程描述完了,实际上在 DNS 解析过程中会存在许多缓存来进一步提高解析速度:

  • 浏览器缓存:浏览器缓存会对是 DNS 解析结果做一定的缓存,其作为 DNS 解析查询的第一步
  • 操作系统级缓存:操作系统缓存作为是 DNS 解析的第二步,也是本地解析的最后一步。这个过程通常称为 “存根解析器”或 DNS 客户端。当存根解析器获取来自某个应用程序的请求时,其首先检查自己的缓存,以便查看是否有此记录。如果没有,则将本地网络外部的 DNS 查询(设置了递归标记)发送到 DNS 递归解析器。
  • 路由器缓存:默认一般路由器的 DNS 常见设置是 192.168.0.1,所以 DNS 客户端实际上会往路由器发送解析请求,路由器本身并没有解析能力,它只会做一个转发以及缓存。当然这一层缓存不一定会走,比如我们可以在本机设备直接设置 DNS 服务器到 8.8.8.8 就不会走路由器了。

上面的几种缓存可以说是“客户端”的缓存,此时都不涉及 DNS 服务器。实际上 DNS 递归解析器也会缓存解析信息。当路由器接收到解析请求时默认会想 ISP 提供 DNS 递归解析器发送递归查询的请求,当 ISP 内的递归解析器收到 DNS 查询时,其还将查看所请求的主机到 IP 地址转换是否已经存储在其本地持久性层中,根据其缓存中具有的记录类型,递归解析器的解析过程会有所不同,比如:

  • 如果此时解析器已存在其对应的权威域名服务器的 NS 记录(比如已经知道了 zzcoder.cn 所在权威服务器的地址 f1g1ns2.dnspod.net),那么此时解析器只需要向 f1g1ns2.dnspod.net 请求解析即可
  • 如果此时解析器已存在对应的 TLD 服务器(比如 .cn)的地址,那么只需要请求 TLD 服务器和权威服务器即可
  • 如果此时解析器没有对应 TLD 服务器的记录,才会额外查询根域名服务器

DNS 记录

上面说的权威服务器保存了 DNS 记录,那么 DNS 记录是什么呢?常见的是 A 记录,CNAME 记录等,如下表所示:

记录类型 说明
A 地址记录,用于将主机名映射到其 IPv4 地址。
AAAA IPv6 地址记录,用于将主机名映射到其 IPv6 地址。
MX 邮件交换记录,用于将请求路由到邮件服务器。
NS 域名服务器记录,用于将 DNS 委托给权威服务器。
CNAME 规范名称记录,用于指定别名。

还有一种比较特殊的记录叫做胶水记录,胶水记录也是在域名注册商处创建的 DNS 记录。一般为域名服务器对应的 IP 地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
λ zhang [~] → dig zzcoder.cn @198.41.0.4

; <<>> DiG 9.10.6 <<>> zzcoder.cn @198.41.0.4
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 57204
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 8, ADDITIONAL: 11
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;zzcoder.cn. IN A

;; AUTHORITY SECTION:
cn. 172800 IN NS c.dns.cn.
cn. 172800 IN NS g.dns.cn.
cn. 172800 IN NS b.dns.cn.
cn. 172800 IN NS ns.cernet.net.
cn. 172800 IN NS e.dns.cn.
cn. 172800 IN NS f.dns.cn.
cn. 172800 IN NS a.dns.cn.
cn. 172800 IN NS d.dns.cn.

;; ADDITIONAL SECTION:
c.dns.cn. 172800 IN A 203.119.27.1
g.dns.cn. 172800 IN A 66.198.183.65
b.dns.cn. 172800 IN A 203.119.26.1
ns.cernet.net. 172800 IN A 202.112.0.44
e.dns.cn. 172800 IN A 203.119.29.1
f.dns.cn. 172800 IN A 195.219.8.90
a.dns.cn. 172800 IN A 203.119.25.1
a.dns.cn. 172800 IN AAAA 2001:dc7::1
d.dns.cn. 172800 IN A 203.119.28.1
d.dns.cn. 172800 IN AAAA 2001:dc7:1000::1

;; Query time: 220 msec
;; SERVER: 198.41.0.4#53(198.41.0.4)
;; WHEN: Sun Jul 12 22:45:20 CST 2020
;; MSG SIZE rcvd: 366

上述是对根域名服务器发起 DNS 解析请求,其中返回的 ADDITIONAL SECTION 会包含每个 TLD 服务器域名对应的 A 记录或 AAAA 记录,这些就是胶水记录。为什么需要它们呢?因为 DNS 解析过程中,无法通过域名来访问域名服务器,如果没有胶水记录,就需要额外根据域名服务器的域名先获取到域名服务器的 IP,这样才能进一步获取目标域名的 IP,因此域名服务器在向更高级别的域名服务器提供本地的域名的时候还会提供对应 IP 地址,以便在后续的 DNS 解析时防止出现循环。

DNS 的常见攻击

DNS 是一种基于 UDP 的应用层协议,容易出现伪造,放大等攻击,以下是 DNS 比较常见的攻击:

  • DNS 缓存投毒(污染):这是将伪造的 DNS 数据引入 DNS 解析器缓存中的攻击,其将导致解析器返回域的错误 IP 地址。本质上攻击者只需要监听域名查询请求,一旦发现目标域名即可将自己伪装成目标域名的权威域名服务器返回虚假的查询结果,而 DNS 解析器一般都会有缓存机制,因此这个域名在 DNS 解析器缓存中就被污染了。

    UDP 其中的一个特点是没有验证机制,非常容易伪装,当系统将 DNS 查询请求发出后,系统会接受第一个返回的结果作为使用,其后的将会被抛弃。因此投毒服务器只要快于真正的权威域名服务器返回即可

  • DNS 劫持:DNS 劫持的结果和 DNS 污染的结果类似,会返回虚假的解析结果,但是攻击手段不同,其目标是域名服务器上网站的 DNS 记录,而不是解析器的缓存。比如篡改 hosts 文件,ISP 对修改某些 DNS 解析记录,篡改DNS权威记录指向自己的恶意服务器以实现DNS劫持等等

  • DNS放大攻击:攻击者通常使用僵尸网络向公用的 DNS 解析器发送大量 DNS 查询请求,并伪造 IP 地址来源设置为受害者,再利用放大效果(比如发送者给 DNS 解析器 10 个字节,DNS 解析器返回 100 个字节),这样受害者的服务将收到大量且并不需要的 DNS 响应从而导致其崩溃,这也是 DDos 攻击的一种类型

DNS 污染问题不是不可避免的,比如现在流行的 DNSSEC 协议,DNSSEC 通过基于公共密钥加密数字签名在 DNS 协议中新增了两项重要功能:

  • 数据来源验证 - 解析器可以通过加密的方式验证收到的数据是否确实来自其认定的数据传送区域。
  • 数据完整性保护 - 解析器可以确信,自区域所有者使用区域私钥初次进行数据签名以来,数据在传输过程中并未遭到修改。

篇幅原因这里不对该协议深入,有兴趣的人可以去研究更详细的原理

Anycast DNS

之前提到目前全球的根域名服务器的任播(Anycast)地址共有 13 个,那么任播代表什么呢,又为什么需要任播呢?其实很简单,一般来说一个 IP 地址对应一个服务器,如果全世界只有 13 台服务器如果高性能的处理全世界的请求以及各种恶意攻击呢?再比如,公开的 DNS 解析器如 1.1.1.1 只需要一个 IP 却用来响应全球的所有请求,如果只有一台服务器如何支持这么高的并发呢?在 Anycast 中,一个 IP 地址可以应用于许多服务器。Anycast DNS 意味着一组 DNS 服务器中的任何一台都可以响应 DNS 查询,通常由地理位置最接近的一台提供响应。

anycast-dns

这样的好处有几个:

  • Anycast 网络对一个 IP 地址的请求可以由许多服务器答复,可以解决单台服务器的单点问题
  • Anycast 具有负载均衡能力,根据网络情况选择地理位置最接近的一台提供响应,有效减少响应延迟
  • Anycast 网络可以提供 DDoS 防护,因为流量可以分散到整个集群

DNS 智能解析

如果使用 DNSPod(国内比较流行的域名解析厂商)就会发现它允许我们为同个域名设置多个 IP,并且允许设置在不同网络返回不同的 IP(比如国内/国外),那么它是怎么做到的呢?其实本质上 DNSPod 作为权威域名服务器它只需要知道请求解析的来源 IP 就可以根据地区来返回不同的 IP。因此类似 8.8.8.8 这样的 DNS 解析器在请求权威服务器的时候需要传入请求者 IP 这样就能完成智能解析,而这就是 EDNS 协议(edns-client-subnet)。它是一个 DNS 扩展协议,允许 DNS 解析器传递用户的 IP 地址给 Authoritative DNS server。DNSPod 支持了这种协议因此能够完成智能解析。比如我将 auto.zzcoder.cn 的境内解析到 6.4.7.8,境外解析到 9.8.3.4,此时分别通过国外/国内客户端 IP 来访问,并使用阿里 DNS 服务器 223.6.6.6 进行解析就会返回不同的结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
λ zhang [~] → dig auto.zzcoder.cn +subnet=199.193.127.121 @223.6.6.6

; <<>> DiG 9.10.6 <<>> auto.zzcoder.cn +subnet=199.193.127.121 @223.6.6.6
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 49896
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1408
; CLIENT-SUBNET: 199.193.127.121/32/24
;; QUESTION SECTION:
;auto.zzcoder.cn. IN A

;; ANSWER SECTION:
auto.zzcoder.cn. 600 IN A 9.8.3.4

;; Query time: 40 msec
;; SERVER: 223.6.6.6#53(223.6.6.6)
;; WHEN: Mon Jul 13 23:33:30 CST 2020
;; MSG SIZE rcvd: 72


λ zhang [~] → dig auto.zzcoder.cn +subnet=122.231.108.109 @223.6.6.6

; <<>> DiG 9.10.6 <<>> auto.zzcoder.cn +subnet=122.231.108.109 @223.6.6.6
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 20362
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1408
; CLIENT-SUBNET: 122.231.108.109/32/24
;; QUESTION SECTION:
;auto.zzcoder.cn. IN A

;; ANSWER SECTION:
auto.zzcoder.cn. 600 IN A 6.4.7.8

;; Query time: 52 msec
;; SERVER: 223.6.6.6#53(223.6.6.6)
;; WHEN: Mon Jul 13 23:33:41 CST 2020
;; MSG SIZE rcvd: 72

不是所有的 DNS 解析器和权威服务器都支持 EDNS

# DNS, UDP

Commentaires

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×