DNS

什么是 DNS

在解释 DNS 之前,我们可以先想象一个场景,就是当你想打电话给某个人的时候,除非你对这个人的电话号码很熟悉,那么你可以一次性地输入这个人的号码并呼叫他,但是,更多的时候,我们是从电话本中找到这个人的名字,然后再选择这个人的某个电话进行呼叫。

那么对应于互联网来说,也是类似的,对于接入互联网的每个设备(这里是指直接接入,而不包含路由器的情况)都有唯一的标识,这个标识以前都是 IPv4,但是,近 10 年来,开始普及 Ipv6 了,那么,当我们想访问某个设备的时候(可能是某个大公司的服务器),那么直接输入 ip 理论上不太行(不是绝对不行),但是这不仅让我们的记忆麻烦,而且对于企业品牌来说也不友好,所以这里就引入了一个给 IP 命名的方式,你可以理解成它就是 DNS 了。这是狭义的理解,如果我们要严格来说,DNS 不仅仅是做 IP 解析,还包含很多的东西,比如邮箱服务,TXT 记录等,但是,这里我想描述的主要就是 IP 解析。

域名的分类

现在的国际域名主要可以分成四类,这里的专业名词叫做 zone(注意了,后续有用到):

  1. 根域(Root Zone)
    • 根域名服务器负责解析顶级域名,给出顶级域名的 DNS 服务器地址;
    • 世界上仅有十三个根域名服务器,这些服务器的 ip 地址是不会随便更改的;
    • 它的域名是空字符串。而全限定域名(FQDN)是 .,因为 FQDN 总是以 . 结尾;
  2. 顶级域(Top Level Domains, TLD):.com .cn 等国际、国家级的域名
    • 顶级域名服务器负责解析次级域名,给出次级域名的 DNS 服务器地址。
    • 每个顶级域名都对应各自的服务器,它们之间是完全独立的。.cn 的域名解析仅由 .cn 顶级域名服务器提供。
    • 目前国际 DNS 系统中已有上千个 TLD,包括中文「.我爱你」甚至藏文域名,详细列表参见 IANA TLD 数据库
    • 除了国际可用的 TLD,还有一类类似「内网 IP 地址」的“私有 TLD”,最常见的比如 xxx.local xxx.lan,被广泛用在集群通信中。后面详细介绍
  3. 次级域(Second Level Domains):这个是个人/企业能够买到的域名,比如 google.com
    • 每个次级域名都有一到多个权威 DNS 服务器,这些 DNS 服务器会以 NS 记录的形式保存在对应的顶级域名(TLD)服务器中。
    • 权威域名服务器则负责给出最终的解析结果:ip 地址(A 记录 ),另一个域名(CNAME 记录)、另一个 DNS 服务器(NS 记录)等。
  4. 子域(Sub Domians)*.google.com 统统都是 google.com 的子域。
    • 每一个子域都可以有自己独立的权威 DNS 服务器,这通过在子域中添加 NS 记录实现。

域名解析协议

在学习网络知识的时候,我们可能已经被灌输了 DNS 使用的 UDP 协议,这在以前是正确的,但是,随着网络的发展,传统的 UDP DNS 解析协议因为不安全的缘故(国内的同学应该有所体会,比如访问一个正规的网站但是发现这个网站有很多莫名其妙的广告),所以出现了支持 TLS 的 DNS 协议,还有以 https 或者 grpc 作为底层协议的基于 TCP 的 DNS 协议。

配置文件

在 Linux 中,关于 DNS 的解析,有 3 个 /etc 目录下的文件我们需要关注,分别是:

  1. /etc/hosts 配置域名与IP对应关系
  2. /etc/resolv.conf 配置DNS服务器
  3. /etc/nsswitch.conf 配置解析顺序,是先解析hosts文件,还是先解析DNS服务器
  4. /etc/host.conf:已被放弃

nsswitch.conf

nsswitch.conf(Name Service Switch configuration file) 是系统用来对 Name 服务控制使用的,它可以控制系统解析的元数据,例如对于 DNS 解析:

  1. [root@liqiang.io]# cat /etc/nsswitch.conf| grep hosts
  2. hosts: files dns

从这里的配置可以看出,我们的配置是先进行 files 的解析,如果解析不成功了,再尝试 dns 解析。

hosts 文件

  1. [root@liqiang.io]# cat /etc/hosts
  2. cat /etc/hosts
  3. 127.0.0.1 localhost
  4. 127.0.1.1 work-pc
  5. 127.0.0.1 google.com

resolv.conf文件

配置 Linux 系统 DNS 服务器的配置文件:

  1. [root@liqiang.io]# cat /etc/resolv.conf
  2. # Generated by NetworkManager
  3. nameserver 8.8.8.8
  4. nameserver 1.1.1.1
  5. nameserver 192.168.121.1

这里只是设置了 3 个 DNS 服务器,没有其他的特别设置,那么在这种默认的情况下,当系统需要进行 DNS 解析的时候,系统永远都会尝试用第一个 DNS 服务器进行解析,只有在第一个 DNS 服务器解析不成功的时候才会继续尝试第二个,否则直接就用第一个的结果。

那么如果我们不希望永远只使用第一个,我们希望能够轮询地使用这三个那么应该怎么办呢?这个时候我们可以配置一个参数 options

  1. [root@liqiang.io]# cat /etc/resolv.conf
  2. # Generated by NetworkManager
  3. nameserver 8.8.8.8
  4. nameserver 1.1.1.1
  5. nameserver 192.168.121.1
  6. options rotate timeout:1 ndots:5

这里我配置了几个 options:

我们验证一下就会发现,它会轮询地使用各种 DNS 服务器:

  1. [root@liqiang.io]# cat test.py
  2. import requests
  3. for domain in [
  4. "https://cloudflare.com",
  5. "https://google.com",
  6. ]:
  7. requests.request("GET", domain)
  8. [root@liqiang.io]# tcpdump -n -t port 53
  9. IP 192.168.121.42.47385 > 8.8.8.8.domain: 34152+ A? cloudflare.com. (32)
  10. IP 8.8.8.8.domain > 192.168.121.42.47385: 34152 2/0/0 A 104.16.133.229, A 104.16.132.229 (64)
  11. IP 192.168.121.42.42714 > 1.1.1.1.domain: 35683+ A? www.cloudflare.com. (36)
  12. IP 1.1.1.1.domain > 192.168.121.42.42714: 35683 2/0/0 A 104.16.124.96, A 104.16.123.96 (68)
  13. IP 192.168.121.42.55753 > 192.168.121.1.domain: 7003+ A? google.com. (28)
  14. IP 192.168.121.1.domain > 192.168.121.42.55753: 7003 6/0/0 A 172.253.118.139, A 172.253.118.102, A 172.253.118.100, A 172.253.118.101, A 172.253.118.113, A 172.253.118.138 (124)
  15. IP 192.168.121.42.41275 > 8.8.8.8.domain: 32237+ A? www.google.com. (32)
  16. IP 8.8.8.8.domain > 192.168.121.42.41275: 32237 6/0/0 A 64.233.170.106, A 64.233.170.104, A 64.233.170.105, A 64.233.170.103, A 64.233.170.99, A 64.233.170.147 (128)

host.conf 文件

这个现在基本已经不用了,都改为 nsswitch.conf了。

配置文件关系

我们在上面有几个配置文件,那么在真正进行 DNS 解析的时候,他们之间的关系是怎么样的呢?

  1. 首先看 nsswitch 文件,里面会指定是先进行 file 解析,还是 dns 解析;
  2. 如果是先进行 file 解析,那么就先查看 /etc/hosts 文件中的配置,存在了就返回,不存在的话就继续使用 dns 解析;
  3. 如果是进行 dns 解析,就会根据 /etc/resolv.conf 文件中的配置,向指定的 DNS 服务器进行解析,解析成功则返回,解析失败那么将返回 unkowns hosts

参考