DNS 原理解析
DNS 是一个分布式的树状命名系统,它就像一个去中心化的分布式数据库,存储着从域名到 IP 地址的映射,本文将介绍 DNS 的原理和常见问题。
工作原理
作为用户访问互联网的第一站,当一台主机想要通过域名访问某个服务的内容时,需要先通过当前域名获取对应的 IP 地址。这时就需要通过一个 DNS 解析器负责域名的解析,下面的图片展示了 DNS 查询的执行过程:
- 本地的 DNS 客户端向 DNS 解析器发出解析
houmin.cc域名的请求; - DNS 解析器首先会向就近的根 DNS 服务器
.请求顶级域名 DNS 服务的地址; - 拿到顶级域名 DNS 服务
cc.的地址之后会向顶级域名服务请求负责houmin.cc.域名解析的命名服务; - 得到授权的 DNS 命名服务时,就可以根据请求的具体的主机记录直接向该服务请求域名对应的 IP 地址;
DNS 客户端接受到 IP 地址之后,整个 DNS 解析的过程就结束了,客户端接下来就会通过当前的 IP 地址直接向服务器发送请求。
对于 DNS 解析器,有两种常见的查询方式,这里使用的是迭代查询:
- 迭代查询:
- 每个 DNS 服务并不会直接返回 DNS 信息,而是会返回另一台 DNS 服务器的位置
- 由客户端依次询问不同级别的 DNS 服务直到查询得到了预期的结果
- 递归查询:
- DNS 服务器收到客户端的请求之后会直接返回准确的结果
- 如果当前服务器没有存储 DNS 信息,就会访问其他的服务器并将结果返回给客户端
域名层级
域名层级是一个层级的树形结构,树的最顶层是根域名,一般使用 . 来表示,以ru.wikipedia.org为例,org为顶级域名,wikipedia为二级域名,ru为三级域名,域名树状组织结构如下图所示。一般 ru.wikipedia.org 省略了最后的.,也就是全称域名(FQDN)ru.wikipedia.org.
根域名下面的就是 com、net 和 org 等顶级域名以及次级域名 wikipedia.org.,我们一般在各个域名网站中购买和使用的都是次级域名、子域名和主机名了。
域名服务器
既然域名的命名空间是树形的,那么用于处理域名解析的 DNS 服务器也是树形的,只是在树的组织和每一层的职责上有一些不同。DNS 解析器从根域名服务器查找到顶级域名服务器的 IP 地址,又从顶级域名服务器查找到权威域名服务器的 IP 地址,最终从权威域名服务器查出了对应服务的 IP 地址。
|
|
我们可以使用 dig 命令追踪 draveness.me 域名对应 IP 地址是如何被解析出来的,首先会向预置的 13 组根域名服务器发出请求获取顶级域名的地址:
|
|
Root DNS Server 是 DNS 中最高级别的域名服务器,这些服务器负责返回 Top Level 地址,这些域名服务器的数量总共有 13 组,域名的格式从上面返回的结果可以看到是
.root-servers.net,每个根域名服务器中只存储了顶级域服务器的 IP 地址,大小其实也只有 2MB 左右,虽然域名服务器总共只有 13 组,但是每一组服务器都通过提供了镜像服务,全球大概也有几百台的根域名服务器在运行。
在这里,我们获取到了以下的 5 条 NS 记录,也就是 4 台 cc. 定义域名 DNS 服务器:
|
|
当 DNS 解析器从根域名服务器中查询到了顶级域名 .cc 服务器的地址之后,就可以访问这些顶级域名服务器其中的一台 ac2.nstld.com 获取权威 DNS 的服务器的地址了:
|
|
这里的权威 DNS 服务是作者在域名提供商进行配置的,当有客户端请求 houmin.cc 域名对应的 IP 地址时,其实会从作者使用的 DNS 服务商 DNSPod 处请求服务的 IP 地址:
|
|
最终,DNS 解析器从 dns8.hichina.com 服务中获取了当前博客的 IP 地址 140.205.41.14,浏览器或者其他设备就能够通过 IP 向服务器获取请求的内容了。
从整个解析过程,我们可以看出 DNS 域名服务器大体分成三类,根域名服务、顶级域名服务以及权威域名服务三种,获取域名对应的 IP 地址时,也会像遍历一棵树一样按照从顶层到底层的顺序依次请求不同的服务器。
127.0.0.53
在前面的命令中,我们看到最初访问根域名服务器来自于 127.0.0.53:53 的响应,我们知道,所有的 127.x.x.x 地址都指向本地机器,并且绑定在 lo 设备上。那么,是什么服务监听在这个地址呢?
|
|
可以看到,是 systemd-resolve 作为本机的 DNS Server,查看 /etc/resolve.conf
|
|
我们已经在 /etc/resolv.conf 中看到,这个文件并不是手动维护的,也不应该直接修改,而是由 systemd 服务 systemd-resolved 来负责维护管理的:
|
|
可见,当前本机的 DNS Server 是 systemd-resolve,并且后者是一个 DNS stub,那么真正的 DNS 服务 IP 是多少呢?我们可以使用如下的命令查看:
|
|
胶水记录
假设我们访问 houmin.site,在通过服务器解析域名的过程中,我们看到当请求 site. 顶级域名服务器的时候,其实返回了 e.nic.site. 等域名:
|
|
就像我们最开始说的,在互联网中想要请求服务,最终一定需要获取 IP 提供服务的服务器的 IP 地址;同理,作为 e.nic.site. 作为一个 DNS 服务器,我也必须获取它的 IP 地址才能获得次级域名的 DNS 信息,但是这里就陷入了一种循环:
- 如果想要获取
houmin.site的 IP 地址,就需要访问me顶级域名服务器e.nic.site - 如果想要获取
e.nic.site的 IP 地址,就需要访问me顶级域名服务器e.nic.site - 如果想要获取
e.nic.site的 IP 地址,就需要访问me顶级域名服务器e.nic.site - …
为了解决这一个问题,我们引入了胶水记录(Glue Record)这一概念,也就是在出现循环依赖时,直接在上一级作用域返回 DNS 服务器的 IP 地址:
|
|
也就是同时返回 NS 记录和 A(或 AAAA) 记录,这样就能够解决域名解析出现的循环依赖问题。
域名记录
- A 记录: 将域名指向一个 IPv4 地址(例如:100.100.100.100),需要增加 A 记录
- CNAME 记录: 如果将域名指向一个域名,实现与被指向域名相同的访问效果,需要增加 CNAME 记录。这个域名一般是主机服务商提供的一个域名
- MX 记录: 建立电子邮箱服务,将指向邮件服务器地址,需要设置 MX 记录。建立邮箱时,一般会根据邮箱服务商提供的 MX 记录填写此记录
- NS 记录: 域名解析服务器记录,如果要将子域名指定某个域名服务器来解析,需要设置 NS 记录
- TXT 记录: 可任意填写,可为空。一般做一些验证记录时会使用此项,如:做 SPF(反垃圾邮件)记录
- AAAA 记录: 将主机名(或域名)指向一个 IPv6 地址(例如:ff03:0:0:0:0:0:0:c1),需要添加 AAAA 记录
- SRV 记录: 添加服务记录服务器服务记录时会添加此项,SRV 记录了哪台计算机提供了哪个服务。格式为:服务的名字.协议的类型(例如:_example-server._tcp)。
- SOA 记录: SOA 叫做起始授权机构记录,NS 用于标识多台域名解析服务器,SOA 记录用于在众多 NS 记录中那一台是主服务器
- PTR 记录: PTR 记录是 A 记录的逆向记录,又称做 IP 反查记录或指针记录,负责将 IP 反向解析为域名
- 显性 URL 转发记录: 将域名指向一个
http(s)协议地址,访问域名时,自动跳转至目标地址。 - 隐性 UR 转发记录 L: 将域名指向一个
http(s)协议地址,访问域名时,自动跳转至目标地址,隐性转发会隐藏真实的目标地址。
参考资料
-
No backlinks found.