简单聊聊DNS
本文主要内容源自 计算机网络(原书第7版)
本文是笔者在学习的过程中整理的内容
1. DNS的功能
DNS的主要作用我们都知道是将域名解析为IP地址,这是因为我们人类往往擅长记忆一些名字和字符,而不擅长冗长的数字,但实际的网路连接和路由中又需要具体的IP地址而非无规律的字符。
但除此以外,DNS还具备如下功能:
- 主机别名。这主要靠DNS的CNAME记录实现(关于CNAME下面我们会说),比如你现在的服务器域名是
c6282k4786.qficp.xyz
,这很长很难记住,这时你想换个更简单的域名如coderzoe.com
,因为简单的域名更利于你网站的推广,但你又不想老的域名失效(比如有些老用户是使用老域名访问的),此时就可以做到将coderzoe.com
域名指向c6282k4786.qficp.xyz
。 - 解析邮箱服务。我们常使用的如
xxx@qq.com
或者xxx@163.com
其中qq.com
和163.com
都是邮箱服务器的域名,这些域名也需要解析为IP地址,因此DNS除了解析Web端的域名还会解析邮箱的域名。这主要靠DNS的MX记录实现(关于MX我们下面也会说)。事实上MX记录允许一个公司的邮件服务器和Web服务器使用相同的域名(如网站https://qq.com
和邮箱xxx@qq.com
)。 - 负载均衡。一个域名可以对应多个IP地址,当客户端向DNS服务器发起某一域名的查询请求时,如果这个域名对应一个IP集合,那么DNS服务器往往会将这整个集合响应给客户端,但在每个响应中循环这些地址次序。因为客户通常总是向IP地址排在最前面的服务器发送HTTP请求报文,所以 DNS就在这些IP地址集对应的服务器集之间循环实现了负载均衡。
2. DNS记录
本文不详细展开DNS的报文,只简单讲下DNS记录。DNS记录大致可以概括为一个四元组:
(Name,Value,Type,TTL)
其中TTL是当前记录的有效时间,我们暂时忽略掉。Type是DNS的类型,Name和Value的取值取决于Type,目前DNS主要有4种Type:
- Type = A,往往叫A记录。它的Name是域名而Value是该域名对应的IP地址。比如
(baidu.com, 172.83.159.98, A)
就是一条A记录,它最根本的作用就是提供了域名和IP地址的映射关系,当我们向DNS请求baidu.com
的IP地址时,DNS服务器会响应这样一条A记录给我们。 - Type = CNAME,往往叫CNAME记录。它的Name是域名,而Value也是个域名,比如
(coderzoe.com, baidu.com, CNAME)
,我将coderzoe.com
域名指向baidu.com
,这样大家输入https://coderzoe.com
响应的就是百度的网站(如果百度服务器未做拦截)。CNAME之所以生效的原因是当客户端向DNS请求coderzoe.com
的IP时,DNS会先发现一个CNAME记录(coderzoe.com, baidu.com, CNAME)
,然后DNS服务器再查询baidu.com
,这时会发现一个(baidu.com, 172.83.159.98, A)
的A记录,最后将这个A记录响应给客户端。 Type = MX,往往叫MX记录。MX记录主要用于邮箱服务器的解析,它的Name是邮箱的域名,而Value也是个域名。比如
(qq.com, mx1.qq.com, MX)
。假设我们想通过QQ邮箱xxx@qq.com
发送邮件,邮箱客户端会向DNS服务器请求qq.com
MX记录,DNS服务器收到请求后,会将(qq.com, mx1.qq.com, MX)
记录返回给邮箱客户端,邮箱客户端再向DNS服务器发起mx1.qq.com
的A记录请求,DNS服务器会将(mx1.qq.com, 113.96.210.17, A)
记录返回给客户端,这样客户端就知道了QQ邮箱服务器的IP地址。我们知道
qq.com
既是TX公司的邮箱域名也是它的Web域名,那当我们向DNS服务器发起qq.com
的请求时,DNS服务器要按邮箱解析还是按Web解析呢?这两种解析情况往往还会对应不同的服务器。为了区别这两种情况,请求客户端会带上自己想要的DNS类型,当进行Web访问的时候,请求就是qq.com+A记录
;而进行邮件发送时,请求客户端会发送qq.com+MX记录
,得到MX记录后再向DNS发送一次A记录请求,最终得到邮箱服务器IP。- Type = NS,往往叫NS记录。NS记录的主要作用是指引DNS的查询路径,告诉客户端去哪里进一步获取查询域的信息。这主要与DNS的工作原理有关,我们来详细的讲一下。
3. DNS工作原理
我们在上文讲到DNS服务器的主要功能是将域名解析为IP地址。为阐述DNS的工作原理,我们假设DNS采用极其简单的一种设计:在互联网上只有一台DNS服务器,且这台服务器上存储了所有的域名映射规则。当我们通过域名浏览网页或者发送邮件的时候,我们的客户端都会向这台服务器发送请求,最终也都能从这台服务器上得到响应。但很可惜,这是不现实的,因为当今的互联网规模已经十分巨大,没有任何一台单体服务器可以处理如此多的规则与如此频繁的请求。且网络的响应时间与物理距离密切相关,距离这台中心DNS服务器较远的客户端响应延迟会更久,用户体验也会更差。
现实中的DNS采用分布式的层次设计,其架构如下图所示:
- 根DNS服务器:存储顶级域名与顶级域DNS服务器关系的DNS服务器。其中顶级域名就是我们域名的最后那一部分,如
.com、.cn、.edu
等。全球共有400多个根DNS服务器。 - 顶级域DNS服务器:存储当前顶级域名下的域名与权威DNS服务器关系的DNS服务器。如
.com
顶级域名DNS服务器存储了baidu.com
域名的权威DNS服务器的信息。 - 权威DNS服务器:我们之前讲的DNS A记录、CNAME记录和MX记录等都存储在权威DNS服务器上。如
(baidu.com, 172.83.159.98, A)
这一记录就存储在一个权威DNS服务器上。
除此以外,这里还有一个十分重要的DNS服务器:本地DNS服务器。每个ISP(如一个小区或者一个机构的ISP)都有一台本地DNS服务器,当我们的电脑接入ISP时,ISP除了可以为当前电脑分配一个IP地址外,还会为其配置本地DNS服务器的IP地址(通过DHCP协议)。
本地DNS的主要功能是代理我们的客户端发请求和缓存DNS记录,我们以一个例子来解释:
我们先假设现在你的电脑和你连接的本地DNS服务器上没有任何DNS记录的缓存。你此刻想通过浏览器浏览https://baidu.com
,当你输入网址按下回车的时候,整个请求流程如下:
- 你的电脑会作为客户端向本地DNS服务器发起请求,本地DNS服务器收到请求后,会直接向根DNS发起请求,向它询问
baidu.com
的DNS信息。 - 根DNS收到请求后,查询自己存储的信息,会向本地DNS服务器响应两条DNS记录:一条是NS记录
(com, b.gtld-servers.net, NS)
另一条是A记录(b.gtld-servers.net, 192.33.14.30, A)
。这代表:虽然我不知道baidu.com
的具体DNS信息,但我知道存储顶级域名.com
信息的DNS服务器,这个服务器是顶级域DNS服务器b.gtld-servers.net
,它的IP地址是192.33.14.30
,你可以问下它。 - 本地DNS服务器收到响应后再向顶级域DNS服务器
192.33.14.30
发起请求,查询baidu.com
的DNS信息。 - 顶级域服务器
192.33.14.30
收到请求后,查询自己存储的信息,向本地DNS服务器响应两条DNS记录,一条是NS记录(baidu.com, dns.baidu.com, NS)
,另一条是A记录(dns.baidu.com, 110.242.68.134, A)
。这代表:虽然我不知道baidu.com
的具体DNS信息,但我知道你可以问下权威DNS服务器dns.baidu.com
,它应该知道,它的IP地址是110.242.68.134
。 - 本地DNS服务器收到响应后再向权威DNS服务器
110.242.68.134
发起请求,查询baidu.com
的DNS信息。 - 权威DNS服务器
110.242.68.134
收到请求后,查询自己存储的信息,向本地DNS服务器响应一条A记录(baidu.com, 172.83.159.98, A)
- 本地DNS服务器收到响应后将A记录
(baidu.com, 172.83.159.98, A)
再响应给我们的浏览器客户端,至此我们的客户端得到了baidu.com
的IP地址是172.83.159.98
。就可以使用这个IP地址做网络连接了。
可以看到上述整个流程中本地DNS服务器分别发了三次baidu.com
的DNS请求,请求的服务器层级由根DNS到.com
顶级域DNS,再到包含baidu.com
的权威DNS服务器。通过这样一层层的迭代查找,我们可以一步步精确的定位到存储baidu.com
域名详细DNS信息的具体服务器。我们也可以看到NS记录的目的是指引本地DNS服务器查询的路径,告诉本地DNS服务器想进一步获取baidu.com
的信息要去哪个服务器。
上述流程中还存在两个缓存,本地电脑的缓存和本地DNS的缓存:
- 当你的浏览器收到
baidu.com
的IP地址后,会将这一信息缓存起来,后续我们再访问baidu.com
的时候就不必继续请求本地DNS了。 - 本地DNS会缓存上述所有的查询过程信息。这样当与你连接同一本地DNS服务器的其他用户想访问
baidu.com
,本地DNS服务器可以直接响应,而无需再请求其他层次的DNS服务器。或者当其他用户想访问qq.com
的时候,本地DNS服务器已经知道.com
顶级域的IP地址,无需再向根DNS服务器获取,可以直接向.com
顶级域DNS服务器查询qq.com
的信息。
DNS缓存不仅改善了请求的时延性能,还有效地减少了在互联网上不必要的DNS请求,从而降低了网络流量和服务器负载。