DNS是什么?
- 域名使用字符串来代替 IP 地址,方便用户记忆,本质上一个名字空间系统;
- DNS 是一个树状的分布式查询系统,但为了提高查询效率,外围有多级的缓存;
- DNS 就像是我们现实世界里的电话本、查号台,统管着互联网世界里的所有网站,是一个 “超级大管家”;
- DNS 服务负责对域名进行解析,获取域名背后映射的 IP 地址,域名的本质是为了方便用户记忆想要与之通信的服务器的地址。(一长串 IP 地址相对于具有实际意义的域名而言,对于用户记忆是不友好的)
DNS域名解析的流程?
就像 IP 地址必须转换成 MAC 地址才能访问主机一样,域名也必须要转换成 IP 地址,这个过程就是 “域名解析”。
目前全世界有几亿个站点,有几十亿网民,而每天网络上发生的 HTTP 流量更是天文数字。这些请求绝大多数都是基于域名来访问网站的,所以 DNS 就成了互联网的重要基础设施,必须要保证域名解析稳定可靠、快速高效。
DNS 的核心系统是一个三层的树状、分布式服务,基本对应域名的结构:
- 根域名服务器(Root DNS Server):管理顶级域名服务器,返回 “com”“net”“cn” 等顶级域名服务器的 IP 地址;
- 顶级域名服务器(Top-level DNS Server):管理各自域名下的权威域名服务器,比如 com 顶级域名服务器可以返回 apple.com 域名服务器的 IP 地址;
- 权威域名服务器(Authoritative DNS Server):管理自己域名下主机的 IP 地址,比如 apple.com 权威域名服务器可以返回 www.apple.com 的 IP 地址。
在这里根域名服务器是关键,它必须是众所周知的,否则下面的各级服务器就无从谈起了。目前全世界共有 13 组根域名服务器,又有数百台的镜像,保证一定能够被访问到。
有了这个系统以后,任何一个域名都可以在这个树形结构里从顶至下进行查询,就好像是把域名从右到左顺序走了一遍,最终就获得了域名对应的 IP 地址。
例如,你要访问 “www.apple.com”,就要进行下面的三次查询:
- 访问根域名服务器,它会告诉你 “com” 顶级域名服务器的地址;
- 访问 “com” 顶级域名服务器,它再告诉你 “apple.com” 域名服务器的地址;
- 最后访问 “apple.com” 域名服务器,就得到了 “www.apple.com” 的地址。
虽然核心的 DNS 系统遍布全球,服务能力很强也很稳定,但如果全世界的网民都往这个系统里挤,即使不挤瘫痪了,访问速度也会很慢。
所以在核心 DNS 系统之外,还有两种手段用来减轻域名解析的压力,并且能够更快地获取结果,基本思路就是 “缓存”。
首先,许多大公司、网络运行商都会建立自己的 DNS 服务器,作为用户 DNS 查询的代理,代替用户访问核心 DNS 系统。这些 “野生” 服务器被称为“非权威域名服务器”,可以缓存之前的查询结果,如果已经有了记录,就无需再向根服务器发起查询,直接返回对应的 IP 地址。
这些 DNS 服务器的数量要比核心系统的服务器多很多,而且大多部署在离用户很近的地方。比较知名的 DNS 有 Google 的 “8.8.8.8”,Microsoft 的“4.2.2.1”,还有 CloudFlare 的“1.1.1.1” 等等。
其次,操作系统里也会对 DNS 解析结果做缓存,如果你之前访问过 “www.apple.com”,那么下一次在浏览器里再输入这个网址的时候就不会再跑到 DNS 那里去问了,直接在操作系统里就可以拿到 IP 地址。
另外,操作系统里还有一个特殊的 “主机映射” 文件,通常是一个可编辑的文本,在 Linux 里是“/etc/hosts”,在 Windows 里是“C:\WINDOWS\system32\drivers\etc\hosts”,如果操作系统在缓存里找不到 DNS 记录,就会找这个文件。
有了上面的 “野生”DNS 服务器、操作系统缓存和 hosts 文件后,很多域名解析的工作就都不用“跋山涉水” 了,直接在本地或本机就能解决,不仅方便了用户,也减轻了各级 DNS 服务器的压力,效率就大大提升了。
下面的这张图比较完整地表示了现在的 DNS 架构。
在 Nginx 里有这么一条配置指令 “resolver”,它就是用来配置 DNS 服务器的,如果没有它,那么 Nginx 就无法查询域名对应的 IP,也就无法反向代理到外部的网站。
resolver 8.8.8.8 valid=30s; # 指定 Google 的 DNS,缓存 30 秒
DNS劫持和污染?
DNS 劫持是指通过篡改 DNS 服务器上域名和 IP 地址的对应关系,使得用户在访问特定域名时被重定向到错误的 IP 地址,从而访问到恶意或非预期的网站。
- “域名屏蔽”,对域名直接不解析,返回错误,让你无法拿到 IP 地址,也就无法访问网站;
- “域名劫持”,也叫 “域名污染”,你要访问 A 网站,但 DNS 给了你 B 网站。(如果是在原有网站中返回一些广告还好,只是影响用户的冲浪体验,但是如果直接返回一个套壳的冒牌网站,但是因为用户输入的域名是正确的,因此会毫无察觉的窃取用户的个人信息,敏感信息等数据。
DNS用了什么传输协议?(tcp还是udp)
DNS
同时使用 TCP
和 UDP
协议的 53
号端口。这种单个应用协议同时使用两种传输协议的情况在 TCP/IP
栈也算是个另类。但很少有人知道 DNS
分别在什么情况下使用这两种协议。
DNS
在 区域传输
(同步解析记录)和 DNS
响应大于 UDP
报文最大长度的时候使用 TCP
协议,其他时候使用 UDP
协议。
为什么使用 UDP
快,是 UDP 的最大优势
客户端向 DNS
服务器查询域名,一般返回的内容都不超过 512字节
,用 UDP
传输即可。不用经过三次握手,这样 DNS
服务器负载更低,响应更快。
理论上说,客户端也可以指定向 DNS
服务器查询时用 TCP
,但事实上,很多 DNS
服务器进行配置的时候,仅支持 UDP
查询包。
何时使用 TCP
传输数据大于 UDP 最大报文长度的时候使用 TCP 协议:
首先了解一下 TCP
与 UDP
传送字节的长度限制:
UDP
报文的最大长度为 512
字节,而 TCP
则允许报文长度超过 512
字节。当 DNS
查询超过 512
字节时会将后面的数据部分丢掉,所以这时需要使用 TCP
发送。但是通常传统的 UDP
报文一般不会大于 512
字节。即使 DNS
服务器中符合条件的记录很多, DNS
服务器也会限制最多返回 13条
来防止报文大于 512
字节。
DNS 区域传输的时候使用 TCP 协议:
DNS 的规范规定了 2 种类型的 DNS 服务器,一个叫 主 DNS 服务器
,一个叫 辅助DNS服务器
。 在一个 区
中 主 DNS 服务器
从自己本机的数据文件中读取该区的 DNS
数据信息,而 辅助DNS服务器
则从区的 主 DNS 服务器
中读取该区的 DNS
数据信息。当一个 辅助 DNS 服务器
启动时,它需要与 主 DNS 服务器
通信,并加载数据信息,这就叫做 区传送(zone transfer)
。
辅域名服务器会定时(一般 3 小时)向主域名服务器进行查询以便了解数据是否有变动。如有变动,会执行一次区域传输,进行数据同步。区域传输使用 TCP 而不是 UDP,因为数据同步传送的数据量比一个请求应答的数据量要多得多,且需要保证数据的 可靠性
和 完整性
。
实际的 DNS 查询过程(递归 or 迭代)
解析记录
解析记录存储在域名服务器中,用于表达域名
与 IP
之间的对应关系,称为 记录
(record)。根据使用场景,"记录" 可以分成不同的类型(type),下面列举几个常见的解析记录类型
type | 解释 |
A | 地址记录(Address),返回域名指向的 IPv4 地址。 |
AAAA | AAAA 记录 (AAAA record),返回域名指向的 IPv6 地址。 |
NS | 域名服务器记录(Name Server),返回保存下一级域名信息的服务器地址。该记录只能设置为域名,不能设置为 IP 地址。 |
CNAME | 规范名称记录(Canonical Name),返回另一个域名,即当前查询的域名是另一个域名的跳转,详见下文。 |
MX | 邮件记录(Mail eXchange),返回接收电子邮件的服务器地址。 |
DNS 服务器根据域名的层级,进行分级查询。
需要明确的是,每一级域名都有自己的 NS 记录,NS 记录指向该级域名的域名服务器。这些服务器知道下一级域名的各种记录。
所谓 "分级查询",就是从根域名开始,依次查询每一级域名的 NS 记录,直到查到最终的 IP 地址,过程大致如下。
- 从 "根域名服务器" 查到 "顶级域名服务器" 的 NS 记录和 A 记录(IP 地址)
- 从 "顶级域名服务器" 查到 "次级域名服务器" 的 NS 记录和 A 记录(IP 地址)
- 从 "次级域名服务器" 查出 "主机名" 的 IP 地址
仔细看上面的过程,你可能发现了,没有提到 DNS 服务器怎么知道 "根域名服务器" 的 IP 地址。回答是 "根域名服务器" 的 NS 记录和 IP 地址一般是不会变化的,所以 "根域名服务器" 的 IP 地址已经内置在所有 DNS 服务器里面了。
迭代查询
tips: 一般的 DNS 并不是全程使用迭代或者递归查询,而是使用两种方式结合。这里仅仅是为了演示全程使用迭代查询的过程。
迭代查询的过程其实就是:当域名服务器收到迭代查询请求报文时,需求给出主机 “你下一步应当向哪一个域名服务器进行查询” 的建议,然后由主机进行下一步的查询,当返回内容即没有确切的结果也没有下一步的建议时,DNS 失败。
这里的建议指 NS
或者 CNAME
等记录
请看图(随手画的小度机器人)
可以通过 dig
命令来迭代跟踪 DNS 过程,windows 下 dig
命令的安装请自行百度
dig +trace www.baidu.com
注意:这里客户端如何选择多条 NS
记录中的一条记录进行下一次查询的目标在不同的操作系统中是不一样的,有的系统会选择第一条,有的则会随机选择。所以一般 DNS服务器
都会将最快的 NS
记录放到第一条。
当返回多条 NS
记录时,如果访问的第一条 NS
记录的 IP
查询时,一定时间内无响应,则会开始尝试访问其他 NS
记录的 IP
查询。
如果返回的记录为空,则代表查询失败,结束 DNS
过程。
递归查询
所谓递归查询就是:如果主机所询问的本地域名服务器不知道被查询的域名的 IP地址
,那么本地域名服务器就以 DNS
客户的身份,向其它根域名服务器继续发出查询请求报文 (即替主机继续查询),而不是让主机自己进行下一步查询。因此,递归查询返回的查询结果是所要查询的 IP地址
,或者是报错,表示无法查询到所需的 IP地址
。
主机对域名服务器说:你给我查 www.baidu.com
的 ip
,我不管你怎么查,你要是不知道你就自己去问其他人,我只要结果不要过程🐅。
当然,图还是要上的。
实际的 DNS 查询过程
上面有特别提到,实际的 DNS查询
并不是单纯的迭代或者递归查询,而是相互结合使用,那么什么时候使用递归什么时候使用迭代呢?
主机向本地域名服务器发起的是递归查询,本地域名服务器到其他域名服务器发起的是迭代查询。
由于 www.baidu.com
的解析过程中需要经过一条 CNAME
记录 www.a.shifen.com
,我想大家到现在也已经清楚 CNAME
记录的作用了,后面的例子中我就以 baidu.com
而不是 www.baidu.com
来举例了。(偷懒 )
这里你会发现 baidu.com 和 shifen.com 的授权域名服务器是同一台,这就是上面说的在同一个 区
参考文档:
06 域名里有哪些门道?
https://juejin.cn/post/7035659937166393375