DNS 的基本概念详解

2015-03-19 linux network

在通过浏览器访问某个网站时,或者说访问网络上的服务器时,可以直接使用 IP 地址,但是对于人类来说很难记忆,为此引入了域名,而为了可以做到自动解析,于时就有了 DNS 。

这里详细介绍 DNS 的基本概念。

简介

域名最初是通过手动配置的,在 Linux 中就是通过 /etc/hosts 文件进行配置,但是这种方法的缺陷是无法自动更新,尤其是当有大量服务器需要配置时,为了解决这一问题,于是就有了 DNS 。

最早是伯克利开发了一套分层的管理系统,称为 Berkeley Internet Name Domain, BIND,后来就是全世界使用最广泛的域名系统 Domain Name System, DNS

首先介绍下常用的概念。

常用概念

Fully Qualified Domain Name, FQDN 全限定域名包括了主机名 Hostname 和域名 Domain Name,通过符号 . 进行分割,主机名和域名是相对而言,如下图所示,不同的层级,主机名和域名也不同。

例如,假设提供 Web 服务的主机名为 www 而域名为 foobar.com ,那么对应的 FQDN 就是 www.foobar.com ,也就是我们最常见的地址。

当然,所谓的主机名并非只是一台主机。

dns examples

需要注意的是,并不是以小数点 . 区分主机名和域名,主机名可以为 www.dic ,而域名还是 ksu.edu.tw ,因此此时全名就为 www.dic.ksu.edu.tw

DNS 的阶层架构与 TLD

仍以 ksu.edu.tw 域名为例,如下图所示。

dns examples

在整个 DNS 系统的最上方一定是根服务器,管理了最上层的域名 (Generic TLDs, gTLD.com .org .gov 等等) 以及国家最上层领域名 (Country code TLDs, ccTLD.tw .uk .jp .cn 等) ,这两者称为 Top Level Domains, TLDs

每一层需要向上层 ISP 申请,如 .tw,管理这个领域名的机器 IP 是在台湾,但是 .tw 这部服务器必须向 root . 注册领域名查询授权才行。各层 DNS 都能管理自己辖下的主机名或子领域,因此,.tw 可以自行规划自己的子域名。

每层 DNS 服务器所记录的信息,其实只有其下层的主机名而已;至于再下一层,则直接授权给下层的主机来管理。

顶层服务器

目前,世界上只有 13 个顶级根域名服务器,可以通过 www.internic.net 查看。需要注意的是,这里所说 13 个根 DNS 服务器,指的是逻辑上有 13 个,而不是物理上 13 个服务器。

实际上,目前物理上有几百个根服务器,大部分通过任播技术与逻辑服务器对应,当前的根服务器可以通过 www.root-servers.org 查看,那么,为什么全球 DNS 根服务器只有 13 组。

DNS 协议最初从 20 世纪 80 年代未期开始算起,使用了端口上的 UDP 和 TCP 协议;UDP 用于查询和响应,TCP 用于主从服务器之间的区传送。

在 Internet 数据传输中,UDP 数据长度控制在 576 字节 (Internet 标准 MTU 值),而在许多 UDP 应用程序设计中数据包被限制成 512 字节或更小,这样可以防止数据包的丢失。

而 512 字节对于在每个包中必须含有数字签名的一些 DNS 新特性(如DNSSEC)来说实在是太小了。如果要让所有的根服务器数据能包含在一个 512 字节的 UDP 包中,根服务器只能限制在 13 个,而每个服务器要使用字母表中的单个字母命名。

注意,大部分的客户端会先通过 UDP 查询,如果发现被截断,那么会重新使用 TCP 再次查询,这样就可以绕过 512 字节的限制,但是会降低查询效率。

解析过程详解

接下来详细查看下 DNS 解析的具体执行过程。

1. 查询 DNS 服务器 IP

我们的电脑通过 ISP 接入互联网,ISP 会分配一个 DNS 服务器,这个 DNS 服务器不是权威服务器,而是一个代理 DNS 服务器,用来代理查询 IP,可以查看 /etc/resolv.conf 文件。

注意,老的 Linux 发行版本,该文件是手动编辑的,现在很多 (如 CentOS) 是自动生成的,详见 resolv.conf 简介

2. 发起请求

向上述的 DNS 服务发起请求查询 www.baidu.com 这个域名了,当然详细信息可以通过 dig +trace www.baidu.com 查看,不过在国内的环境经常出错,那我们就一步一步来查看。

3. 如果有缓存直接返回

上述服务器收到请求后,如果自己缓存中有这个地址,则直接返回,且标记为非权威服务器应答。

4. 没有命中,则从根开始查询

如果缓存中没有,则会开始查询 13 个根域名服务器的地址,这些地址是不变的,可以直接保存在 BIND 的配置文件中。

可以直接通过如下方式查询。

$ dig @a.root-servers.net root-servers.net ns
ROOT-SERVERS.NET.       141973  IN      NS      h.ROOT-SERVERS.NET.
ROOT-SERVERS.NET.       141973  IN      NS      i.ROOT-SERVERS.NET.
ROOT-SERVERS.NET.       141973  IN      NS      k.ROOT-SERVERS.NET.
ROOT-SERVERS.NET.       141973  IN      NS      b.ROOT-SERVERS.NET.
ROOT-SERVERS.NET.       141973  IN      NS      j.ROOT-SERVERS.NET.
ROOT-SERVERS.NET.       141973  IN      NS      g.ROOT-SERVERS.NET.
ROOT-SERVERS.NET.       141973  IN      NS      e.ROOT-SERVERS.NET.
ROOT-SERVERS.NET.       141973  IN      NS      l.ROOT-SERVERS.NET.
ROOT-SERVERS.NET.       141973  IN      NS      m.ROOT-SERVERS.NET.
ROOT-SERVERS.NET.       141973  IN      NS      c.ROOT-SERVERS.NET.
ROOT-SERVERS.NET.       141973  IN      NS      d.ROOT-SERVERS.NET.
ROOT-SERVERS.NET.       141973  IN      NS      f.ROOT-SERVERS.NET.
ROOT-SERVERS.NET.       141973  IN      NS      a.ROOT-SERVERS.NET.

5. 向其中一台根服务器发起请求

根服务器拿到这个请求后,知道他是 com. 这个顶级域名下的,所以就会返回 com 域中的 NS 记录,通常是 13 台主机名和 IP 。

$ dig com. ns                # 同下
$ dig @a.root-servers.net com ns
com.                    17051   IN      NS      i.gtld-servers.net.
com.                    17051   IN      NS      m.gtld-servers.net.
com.                    17051   IN      NS      l.gtld-servers.net.
com.                    17051   IN      NS      j.gtld-servers.net.
com.                    17051   IN      NS      b.gtld-servers.net.
com.                    17051   IN      NS      a.gtld-servers.net.
com.                    17051   IN      NS      k.gtld-servers.net.
com.                    17051   IN      NS      h.gtld-servers.net.
com.                    17051   IN      NS      c.gtld-servers.net.
com.                    17051   IN      NS      d.gtld-servers.net.
com.                    17051   IN      NS      g.gtld-servers.net.
com.                    17051   IN      NS      f.gtld-servers.net.
com.                    17051   IN      NS      e.gtld-servers.net.

6. 向顶级域名服务器发送请求

同样是向其中一台发起请求,请求 baidu.com 这个域的域名服务器。

$ dig @e.gtld-servers.net baidu.com ns
baidu.com.              9141    IN      NS      dns.baidu.com.
baidu.com.              9141    IN      NS      ns7.baidu.com.
baidu.com.              9141    IN      NS      ns2.baidu.com.
baidu.com.              9141    IN      NS      ns3.baidu.com.
baidu.com.              9141    IN      NS      ns4.baidu.com.

7. 再次发送请求

再次向 baidu.com 这个域的权威服务器发起请求,baidu.com 收到之后,查了下有 www 的这台主机,就把这个 IP 返回给你了。

$ dig @dns.baidu.com www.baidu.com
www.baidu.com.          547     IN      CNAME   www.a.shifen.com.
www.a.shifen.com.       144     IN      A       220.181.111.188
www.a.shifen.com.       144     IN      A       220.181.112.244

8. 返回给客户

拿到了 IP 之后将其返回给了客户端,并且把这个保存在高速缓存中。

服务器分类

在如上介绍解析流程的时候,会有关于所谓权威服务器的介绍,这里介绍常见概念。

权威 DNS

权威 DNS 是经过上一级授权对域名进行解析的服务器,每个域都会有域名服务器,也叫权威域名服务器,例如 baidu.com 是一个域名,而 www.baidu.com 主机就是这个域管理的主机。

递归 DNS

会接受用户对任意域名查询,并返回结果给用户,一般会缓存查询结果以避免重复向上查询。

平时使用最多的就是这类 DNS 服务器,会对公众开放服务,一般由网络运营商或者互联网厂商提供,比如谷歌的 8.8.8.8 就属于这一类 DNS 。

转发 DNS

同样负责接受用户查询,并返回结果给用户,这个结果不是按标准的域名解析过程得到的,而是直接把递归 DNS 的结果转发给用户,同样具备缓存功能。

比如路由器里面的 DNS 就是这一类。

记录类型

在 DNS 中最常见的是 Internet 资源,包括了 4 个元组:NameValueTypeTTL。其中 TTL 表示生存时间,决定了多长时间会从缓存中删除;Type 决定了 NameValue,常见有如下几种:

  • A 记录,Address。用于描述域名到 IP 地址的映射,同一个域名可以对应多个记录,也就是一次 DNS 查询可以返回多个 IP,从而可以实现基本的流量均衡。
  • NS 记录,Name Server。域名服务器记录,用于说明这个区域有那些 DNS 服务器来负责解析,每个域可以有多个域名服务器。
  • SOA 记录,Start Of Authority。用于指定该域的权威域名服务器,负责说明负责解析的 DNS 服务器中那个是主服务器,只允许有一个 SOA 记录,它是资源记录的第一个条目。
  • CNAME 记录。描述别名和域名的关系,从而可以允许将多个名字映射到同一台服务器。例如,一台服务器同时提供 WWW 和 MAIL 服务,可以提供两个 www.foobar.com mail.foobar.com 别名同时指向 host.foobar.com 。
  • MX 记录。全称是邮件交换记录,在使用邮件服务器的时候,MX 记录是无可或缺。比如 A 用户向 B 用户发送一封邮件,那么他需要向 DNS 查询 B 的 MX 记录。

FAQ

根域

其实就是所谓的 . 或者根域,是指网址 www.baidu.com 在配置中应该是 www.baidu.com. 只是一般在浏览器输入时会省略后面的点。

A 记录与 CNAME 记录的区别?

A 记录是把一个域名解析到一个 IP 地址,而 CNAME 记录是把域名解析到另外一个域名,而这个域名最终会指向一个 A 记录。

当一台机器提供了多个服务时,这种方式比较容易修改。将多个域名映射到一个相同域名,然后只需要修改被映射的域名即可。

CNAME 的使用

比较常见的一个是 Github 提供的项目 Pages 的支持,一般是类似 PROJECT.github.io 的域名,实际上指向的是一个 CNAME 配置,最终为同一个域名。

根据解析之后的 A 地址,对应的 Web 服务器就可以进行解析处理了。因为基本上就是个静态页面,所以很容易做一些缓存的策略。

PTR 用途

PTR 用于从 IP 地址反查域名,可以使用 dit -x IP 进行反查。

其中的一个场景是防止垃圾邮件,即验证发送邮件的 IP 地址,是否真的有它所声称的域名。

TTL 值

Time To Live, TTL 生存时间,表示解析记录在 DNS 服务器中的缓存时间,默认是 3600 秒。

例如在访问 www.foobar.com 时,如果在 DNS 服务器的缓存中没有该记录,就会向 NS 服务器发出请求,获得该记录后,该记录会在 DNS 服务器上缓存 TTL 的时间长度,在 TTL 有效期内访问 www.foobar.com 时,会直接返回。

DNS 服务器地址

通过 dig 命令查询时,默认会依次查询 /etc/resolv.conf 文件中的地址,至于是从哪个 DNS 服务器地址查询到,可以查看返回结果中的 SERVER 字段,例如:

;; Query time: 1 msec
;; SERVER: 10.0.52.180#53(10.0.52.180)
;; WHEN: Thu May 09 15:38:04 CST 2017
;; MSG SIZE  rcvd: 101

当然,可以在执行时通过 @ 指定,例如如下的方式。

$ dig @8.8.8.8 www.baidu.com

参考