每个前端都该了解的“DNS域名解析”详解

6,312 阅读10分钟
原文链接: zhuanlan.zhihu.com

DNS:Domain Name System(域名服务系统)

DNS的常见用法:将服务器名称和 IP 地址进行关联,但它还可以将邮件地址和邮件服务器进行关联,以及为各种信息关联相应的名称。

为什么需要ip地址

TCP/IP 网络是通过 IP 地址来确定通信对象的,不知道 IP 地址就无法将消息发送给对方,因此,在委托操作系统发送消息时,必须要先查询好对方 的 IP 地址。

TIP:如果 Web 服务器使用了虚拟主机功能,有可能无法通过 IP 地址来访问。因为虚拟主机是寄存在服务器上的一个或多个没有实体的服务器,访问虚拟主机的域名的时候,先根据DNS解析的IP访问到实体主机,然后实体主机再根据域名把连接转发给对应的虚拟主机,DNS解析的IP只是实体主机的IP(并不是要访问的web应用服务器IP地址)。

域名和 IP 地址并用的理由

  • 不用IP 地址,而是用名称来确定通信对象?
    IP 地址的长度 为 32 比特( 4 字节),使用域名最少也要几十个字节,最长可达到255字节,增加了路由器的负担,传送数据也会花费更长的时间 ,运行效率较低。(路由转发包传输数据)
  • 浏览器网址中不写服务器的名字,直接写IP 地址?
    用IP地址来代替服务器名称也是能够正常工作的 。然而,要记住一串由数字组成的 IP 地址也非常困难
  • 让人来使用名称,让路由器来使用IP地址。
    为了填补两者之间的障碍,需要有一个机制能够通过名称来查询IP地址,或者通过IP 地址来查询名称,这个机制就是DNS

TCP/IP 的结构

TCP/IP是是由一些小的子网,通过路由器连接起来组成一个大的网络(子网:用集线器连接起来的几台计算机),在网络中所有的设备都会被分配一个地址,这个地址就相当于现实中某条路上的“×× 号 ×× 室”,(号:分配给整个子网的,室:分配给子网中的计算机的,“号”对应的号码称为网络号,“室”对应的号码称为主机号)这个地址的整体称为IP地址 。通过IP地址我们可以判断出访问对象服务器的位置,从而将消息发送到服务器

发送者发出的消息先经过子网中的集线器,转发到最近的路由器,接下来路由器会根据消息的目的地判断下一个路由器的位置,然后将消息发送到下一个路由器(即消息再次经过子网内的集线器被转发到下一个路由器),前面的过程不断重复,最终消息被传送到了目的地。

实际的IP地址

实际的 IP 地址是一串 32 比特的数字,按照 8 比特(1 字节)为一组分成 4 组,分别用十进制表示,然后再用圆点隔开。

在 IP 地址的规则中,网络号和主机号连起来总共 32 比特,但这两部分的具体结构是不固定的(在组建网络时,用户可以自行决定它们之间的分配关系),无法区分哪部分是网络号,哪部分是主机号。因此:需要另外的附加信息来表示 IP 地址的内部结构。这就需要用到子网掩码,子网掩码的格式是一 串与IP地址长度相同的32比特数字,左边一半都是1,右边一半都是0。子网掩码为1的部分表示网络号,子网掩码为0的部分表示主机号。

IP 地址的主机号:

  • 全 0:表示整个子网
  • 全 1:表示向子网上所有设备发送包,即“广播”

浏览器是如何向 DNS 服务器发出查询

  • 浏览器搜索自身的DNS缓存:
    首先浏览器会去搜索自身的DNS缓存,看缓存有没有过期,过期的话缓存的解析就结束了(chrome缓存的时间只有一分钟,查看chrome的缓存可打开:chrome://net-internals/#dns )。
  • 搜索操作系统自身的DNS缓存:
    如果浏览器没有找到缓存或者缓存过期失效,浏览器就会搜索操作系统自身的缓存,没有找到或者失效,解析结束(操作系统的缓存:window系统是一天,mac系统严格根据DNS协议中的TTL)。
  • 读取本地的hosts文件:
    若操作系统的缓存也没有找到或失效,浏览器就会去读取本地的hosts文件(Hosts文件也可以建立域名到IP地址的绑定关系,可以通过编辑Hosts文件来达到名称解析的目的。 例如,我们需要屏蔽某个域名时,就可以将其地址指向一个不存在IP地址,以达到屏蔽的效果)。
  • 浏览器发起一个DNS的系统调用:
    hosts中没有找到对应的配置项的话,浏览器发起一个DNS的调用(向本地主控DNS服务,一般来说是你的运营商提供的)。

解析器与DNS服务器之间的交互过程

通过 DNS 查询 IP 地址的操作称为域名解析,负责执行解析这一操作的就叫解析器。 解析器实际上是一段程序,它包含在操作系统的 Socket 库中 (Socket 库可以让其他的应用程序调用操作系统的网络功能 )。

解析器的用法非常简单,编写应用程序(这里也就是指浏览器)时,如下图写上解析器的程序名称(gethostbyname)以及web服务的域名(lab.glasscom.com/)进行调用就可以了,这样就完成了对解析器的调用。

应用程序调用解析器图:

整个解析器的工作流程图:

  • 调用解析器后,解析器会向 DNS 服务器(运营商提供的)发送查询消息。
  • 运营商服务会先查找自身缓存找到对应条目,没有过期,解析成功,若没找到对应条目,主控服务器会代替浏览器发起一个迭代的DNS解析的请求,先查找根域的),运营商服务器拿到域名的IP,返回给操作系统的内核,同时缓存在了自己的缓存区,操作系统内核从DNS服务商拿来的IP地址返回给浏览器。
  • 浏览器再向 Web 服务器发送消息时,只要从该内存地址取出 IP地址,将它与 HTTP 请求消息一起交给操作系统 .

TIP:向 DNS 服务器发送消息时,我们当然也需要知道 DNS 服 务器的 IP 地址。只不过这个 IP 地址是作为 TCP/IP 的一个设置项目事先设 置好的,不需要再去查询了。

DNS服务器的基本工作

DNS 服务器的基本工作就是接收来自客户端的查询消息,然后根据消息的内容返回响应

来自客户端的查询消息包含以下 3 种信息

  • 域名:服务器、邮件服务器(邮件地址中@后面的部分)的名称 。
  • Class:用来识别网络的信息(在最早设计 DNS 方案时,DNS 在互联网以外的其他网络中的应用也被考虑到了。不过,如今除了互联网并没有其他的网络了,因此 Class 的值永远是代表互联网的 IN )。
  • 记录类型 :表示域名对应何种类型的记录(例如,A :表示域名对应的是 IP 地址,MX :表示域名对应的是邮件服务器。对于不同的记录类型,服务器向客户端返回的信息也会不同 )。

DNS 服务器上事先保存有前面这 3 种信息对应的记录数据,DNS 服务器的基本工作就是根据需要查询的:域名和记录类型查找相关的记录,并向客户端返回响应消息。

DNS服务上的信息是如何在 DNS 服务器上注册并保存的

DNS 服务器中的所有信息都是按照域名以分层次的结构来保存的,层次有点号来划分:主机名.次级域名.顶级域名.根域名(host.sld.tld.root),越靠近右边级别越高,所有域名后面都是带有根域的,但是一般都省略掉了。

次级域名域名是用户可以注册的,再下一级是主机名(host),又称为"三级域名",这是用户在自己的域里面为服务器分配的名称,是用户可以任意分配的。

前面说过若运营商服务里没有找到对应的条目,就会发起一个DNS迭代请求,首先就是查找根域服务器,那么运营商的服务了一定要保存有根域服务的IP地址。因为全球共有13台根逻辑域名服务器:A-M,2014年统计的真实的根服务器有386台,将根域的 DNS 服务器信息保存在互联网中所有的 DNS 服务器中也不是什么难事。如何实现呢:根域 DNS 服务器的相关信息已经包含在 DNS 服务器程序的配置文件中了,因此只要安装了 DNS 服务器程序,这些信息也就被自动配置好了。

运营商DSN服务器发起的迭代请求

首先运营商服务从已经配置好的信息中拿到根域名的IP地址(这里假设根域只有一个,实际是想13个根域发起请求),然后像根域发起请求群问:"请问lab.glasscom.com的IP地址是多少?",根域名查询记录数据后没有找到,回答:"我不知道它的IP地址,不过我知道.com的权威服务器(ns)的地址,它是xxx.xxx.xxx.xxx,你去问它吧"。运营商服务运营商服务拿到.com的IP地址,根据IP地址发起另一个请求去询问.com服务器问:"请问 lab.glasscom.com的ns的IP地址是多少?",.com域服务器查找自身记录数据后回答:“我不知道,我只知道.glasscom.com的IP地址”。 以此类推,只要重复前面的步骤,就可以顺藤摸瓜找到目标DNS服务器,只要向目标DNS 服务器发送查询消息,就能够得到我们需要的答案,也就是 lab.glasscom.com 的 IP 地址了。

通过缓存加快 DNS 服务器的响应

  • 真实互联网中:一台 DNS 服务器可以管理多个域的信息,上下级域共享同一 台 DNS 服务器,访问上级 DNS 服务器时就可以向下跳过一级 DNS 服务器,直接返回再下一级 DNS 服务器的相关信息。
  • DNS 服务器有缓存功能:并不需要从根域开始查找,通过缓存可以直接返回响应,接下来的查询可以从缓存的位置开始向下进行。相比每次都从根域找起来说,缓存可以减少查询所需的时间。
  • 信息被缓存后,原本的注册信息可能会发生改变,这时缓存中的信息就有可能是不正确的,因此缓存信息会设置有效期,当缓存中的信息超过有效期后,数据就会从缓存中删除。

命令来查看整个DNS请求过程:

显示整个查询过程:dig baidu.com dig +short baidu.com

其它更多查询命令可以参考阮一峰老师的文章:DNS 原理入门 - 阮一峰的网络日志