前言

这个系列的博客是针对阅读《网络是怎样连接的》([日] 户根勤, 译 [中] 周自恒, ISBN: 9787115441249)一书的记录与思路整理。
有些概念是做纯路由交换的网络工程师很少接触但又很重要的部分,因此整理到这里以做分享。

域名和IP 地址并用的理由

TCP/IP 网络必须使用IP 地址来确定通信对象。那为什么作为用户时,很少会碰到直接使用IP 地址的时候,例如访问网页使用的是域名?

  1. 域名方便记忆。实际上使用IP 地址来替代网址也是可以工作的。(实际上当今的服务器软件如果启用了虚拟主机功能,直接使用IP 地址也无法访问)
  2. 运行效率。IP 地址长度为32 bits,即4 bytes。域名大小不定从十几到255字符都是有可能的。如果通过域名来决定如何处理数据包,不仅增加了网络中路由器的负担(域名长度是不固定的。处理长度不固定的数据比处理定长的数据要复杂得多,负担也更重),还减缓了数据传递的速度(因为传递的数据量更大了)
  3. 域名可以使系统具备容灾、负载均衡特性,例如一个域名可以对应多个后台IP,那么我们通过操作DNS 系统就可以将流量负载到不同的后台设备(书上没有,自己补充)

所以当前,互联网使用的方案是让人来使用域名/网站名称,让机器来使用IP 地址。

为了填补域名和IP 地址之间的障碍,我们需要一个机制能够让机器通过名称来查询IP 地址,反之亦然。这个机制就是DNS。

DNS

什么是DNS

DNS:Domain Name System,域名服务系统。将服务器名称和IP 地址进行关联是DNS 最常见的用法。但DNS的功能并不仅限于此,例如可以将邮件地址和邮件服务器关联,以及为各种信息关联相应的名称。

Socket 库提供查询IP 地址的功能

通过DNS 查询IP 地址的方法非常简单,机器只需要询问最近的(指定的)DNS 服务器“www.xxxx.com 的IP 地址是什么”就可以了。

既然有服务器,那么主机上也一定会有客户端。DNS 的客户端被成为DNS 解析器、或者简称解析器。通过DNS 查询IP 地址的操作成为域名解析,负责执行解析(resolution)操作的就叫解析器(resolver)。
解析器实际上是一段程序,包含在操作系统Socket 库中。

“Socket 库是在加州大学伯克利分校开发的 UNIX 系操作系统 BSD 中开发的 C 语言库,互联网中所使用的大多数功能都是基于 Socket 库来开发的。因此,BSD 之外的其他操作系统以及 C 语言之外的其他编程语言也参照 Socket 库开发了相应的网络库。可以说,Socket 库是网络开发中的一种标准库。” - 摘录来自: [日] 户根勤. “网络是怎样连接的。”

浏览器完成DNS 查询的全流程

DNS 服务器的基本工作

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

客户端的查询消息包含3类信息:

信息类型 备注
域名 服务器的名称
邮件服务器(邮件地址中@ 后面的部分)的名称
Class 最早设计DNS 方案时,DNS 在互联网以外的其它网络中的应用也被考虑到了。
如今,除了互联网并没有其它网络用到DNS 了,所以Class 的值永远为IN
记录类型 表示域名对应何种类型的记录。
例如,A 型(Address 的缩写),表示域名对应的是IP 地址。
MX 型,表示域名对应的是邮件服务器。

上图中,DNS 信息以表格的形式表现,表格中的每一行信息被称为一条资源记录。实际上数据是保存在服务器的配置文件中。

示例

DNS 服务器包含以下记录

域名 Class 记录类型 相应数据
www.lab.glasscom.com IN A 192.0.2.226
glasscom.com IN MX 10 mail.glasscom.com
mail.glasscom.com IN A 192.0.2.227

查询www.lab.glasscom.com 域名的IP 地址

客户端向DNS 服务器发送以下信息

域名 Class 记录类型
www.lab.glasscom.com IN A

DNS 服务器查找已有记录,第一条的三个项目完全匹配。则DNS服务器将记录的192.0.2.226 返回给客户端。

Web 服务器的域名很多都以www 开头,这只是一种惯例而已。无论是Webserver1 或MySrv 也好,只要是作为A记录在DNS 服务器上注册,都可以作为Web 服务器的域名。
同理,对于其它类型的服务器(邮件、数据库等),只要注册了A类型,就可以作为服务器的域名来使用。

查询[email protected] 域名的IP

客户端向DNS 服务器发送以下信息

域名 Class 记录类型
glasscom.com IN MX

服务器会返回邮件服务器的域名和优先级。同时还会返回邮件服务器域名的IP 地址。

当一个邮件地址对应多个邮件服务器时,需要根据优先级判断哪个邮件服务器是优先的。优先级数值越小代表邮件服务器更优先。

一个DNS 响应抓包

DNS 记录类型

记录类型 备注
A 查询IP
MX 查询邮件服务器
PTR 根据IP地址反查域名
CNAME 查询域名相关别名
NS 查询DNS服务器IP地址的NS类型
SOA 查询域名属性信息

域名的层次结构

在有限的服务器的情况下,一台DNS 服务器按照上述的模式为主机提供解析服务。但是在互联网环境下,将全球所有的域名信息都记录在一台服务器上显然是不现实的,这时我们将DNS 信息分布式保存在多台DNS服务器中,并通过DNS 服务器互相接力配合来找出主机查询的信息。

DNS 服务器中的所有信息都是按域名以分层次的结构来保存的。
DNS 域名都是通过句点来分隔的,句点就代表了不同层次之间的界限。

在域名中,越靠右的位置表示其层级越高。举例来说www.lab.glasscom.com这个域名如果按照公司的组织架构来说,com 就是集团总部,glasscom是集团总部下面的子公司,lab是子公司内的一个部门,www就是部门中的科室。

对于域名存储来说,注意几点:

  1. 每个域都是作为一个整体来处理的。也就是说一个域的信息是作为一个整体存放在DNS 服务器中,不能将一个域拆开来存放在多个服务器
  2. 一台DNS 服务器中可以存放多个域信息;
  3. 现在管理员是通过创建子域(下级域)来分配给不同的公司、组织和个人的。

寻找合适的DNS 服务器并获取期望的IP 地址过程

  1. 首先将管理下级域的DNS 服务器注册到它们的上级DNS 服务器中;
  2. 然后将上级DNS服务器注册到更上一级DNS 服务器,以此类推;
  3. 这样我们就可以通过上级DNS 服务器查询出下级DNS 服务器发送查询请求了。

根域

要记住comjpcn并非最上级的域,在之上还有一层根域。

如果要明确表示根域就需要在域名后面加上.,例如www.lab.glasscom.com.

根域的DNS 保存着comjpcn等DNS服务器的信息。
根域的另一项工作,就是将根域的DNS 服务器信息保存在互联网上所有的DNS 服务器中。这样一来,在最坏的情况下,任何DNS 服务器也都可以通过访问根域来找到任意一台DNS 服务器获取期望信息。
这项工作并不困难,原因有两点:

  1. 全球只有13个根域DNS IP,且基本不发生变化;
  2. 根域DNS 服务器相关信息包含在DNS 服务器程序的配置文件中了,因此安装了DNS 服务器程序,这些信息会自动配置好(除非手动删除)

DNS 服务器工作流程

  1. 客户端向本机配置好的DNS 服务器(本地DNS 服务器)发起请求,询问www.lab.glasscom.com 的IP地址是多少?
  2. 本地DNS服务器没有保存相关信息,因此本地DNS 服务器将请求转发给根域DNS服务器
  3. 根域也没有详细信息,但是根域查找到管理com域的DNS 服务器地址,因此根域返回它保存的管理com域的DNS 服务器IP
  4. 本地服务器继续向管理com域的DNS服务器请求解析
  5. 管理com域的DNS 服务器也没有保存www.lab.glasscom.com的信息,但是它找到了下级域glasscom.com的管理DNS 服务器,因此它返回下级域IP
  6. 客户端继续向下级域进行解析请求,最终找到存放www.lab.glasscom.com的DNS服务器,获取到www.lab.glasscom.com 的IP 地址

但在实际情况下,很多时候上下级域可能共享同一台DNS服务器,所以DNS服务器收到一个请求后,该服务器会返回当前服务器最下级的数据给客户端。

DNS 缓存

很多时候本地DNS 服务器不需要从根域开始进行DNS 查找,这是因为DNS 服务器有一个缓存功能,可以记住之前查询过的域名。如果要查询的域名和相关信息已经在缓存中,那么可以本地DNS服务器可以直接返回结果。节约了用户的请求时间。

相对的,一个域名被缓存在某个DNS 服务器时,其真实DNS 信息有可能已经修改,这时缓存信息就有可能不正确。DNS 服务器对每个缓存都用设置了一个有效期,当缓存信息超过有效期后,数据就会从缓存中删除。另外,当DNS 服务器使用缓存数据向客户端进行回应时,DNS 服务器也会告知客户端这一响应结果来自缓存而不是负责管理该域名的DNS 服务器。