Introduction to Computer Networking学习笔记(二十六):DNS

DNS应该算是经常听到的名词之一了,它是 Domain Name System 的缩写,旨在提供根据域名获得IP地址的服务。一个URL包含三个部分,第一部分应用层协议类型及端口号,域名代表的host,及host中的文件。DNS即负责告知client域名所对应的的IP。

Introduction to Computer Networking学习笔记(二十六):DNS

DNS有两个特点:

1. 只读或者说大多数情况下只提供读的服务,修改较少

2. 较宽松的一致性要求,即产生延迟影响不大

以上这两点使得DNS系统可以使用缓存,建立了一个域名与IP的映射关系之后可以进行缓存,下次直接使用而不进行查询。

下图是DNS系统的架构图。可以看到DNS是按层级划分的,最顶层是root(dot),下面是*域名,之后层层划分。

Introduction to Computer Networking学习笔记(二十六):DNS

我们从上图可以得到以下一些结论:

1. 采用分级、分区域(edu、com等)的体系

2. 每个层级、每个区域可以分别进行管理

3. 每个区域的服务器都有备份,防止单点故障导致整个网络出现问题

4. root有13个不同的服务器(A~M),并且每个服务器在世界各地有很多的备份,root server的IP就存储在域名服务器上,而域名服务器的地址则可以通过DHCP获取(下一节讲),并且root服务器的备份是通过任播的形式实现的。

DNS请求中包含两种请求方式:递归请求与非递归请求(这两者我认为是这样区分的:A想联系B,如果A联系C,让C去联系B,然后把结果告知A,那么就是递归请求;不同的,如果A联系C,让C告知了B的地址,然后A自己去联系C,则为非递归请求)。DNS使用UDP协议53端口传输,并且受512byte的限制,一旦回复内容大于512byte,则会使用TCP重新请求,为什么不直接使用TCP,因为TCP要握手延迟较高。

那么一个查询过程是怎样的呢,如下图,client通过DHCP知道域名解析服务器的地址并查询,该查询是递归查询,resolver接到请求后根据域名去与root server取得联系,并查询*域名.edu所在服务器地址,该查询是非递归查询(后续皆为非递归查询),获得*域名服务器地址后,继续查询stanford.edu服务器地址,继续查询www.stanford.edu服务器地址,获得地址后返回给client,同时resolver缓存.edu、.stanford.edu、www.stanford.edu的映射关系,后续直接提供服务,而无需再次逐级查询。

Introduction to Computer Networking学习笔记(二十六):DNS

以上是从宏观层面上看到的DNS解析过程,而在具体实现中是如何实现查询的呢。所有的DNS信息以Resource Records(RRs)的形式表达,其结构如下图:首先是信息名称,比如域名;然后是TTL生存时间;然后是等级,通常为IN(1)代表Internet;然后是类型,比如有A(IPv4地址)、NS(name server);最后是rdata,填写资源数据。

Introduction to Computer Networking学习笔记(二十六):DNS

以上是DNS报文的数据区中的内容的表达形式,数据区中可能包含多条RRs。如下图是一个DNS报文的结构:其中除header以外的每一部分都是有一条条RRs组成。

Introduction to Computer Networking学习笔记(二十六):DNS

为了清除的理解,可以看下一条真正的DNS报文如下图:首先是首部,后面的question字段有一条RR,answer字段有两条RR,后面authority字段有4条RR。

Introduction to Computer Networking学习笔记(二十六):DNS

数据区前面的首部:16bit宽,有6行,即12byte

Introduction to Computer Networking学习笔记(二十六):DNS

DNS为了能够尽量使所有信息不超过512byte,有着自己的名称压缩机制。首先我们要知道名字是如何记录的。在DNS中名字的记录也是分层级的,每一个层级为一个标签,比如www.stanford.com,其中www为一个标签,stanford为一个标签,com为一个标签。而在存储时则是长度+内容,长度为一个数字,内容即字符采用ascii形式存储。举个例子www,存储为0x0377 0x7777,第一个byte 0x03代表了长度为3byte,w的ascii码为0x77,因此0x03后跟3个0x77。其他标签亦如此。那么是如何实现压缩机制的呢。就比如一条DNS报文中出现了多次stanford,那么则使用指针的形式代替这个标签,而不需要重复写入stanford。而这是通过偏置实现的。比如第一次出现并完整记录的stanford从第8个byte开始,那么第二次出现时则记为0xc008,为什么是c0呢,因为DNS中规定,原本表示长度的位置如果大于等于192即0xc0,则表示接下来的14bits用来表示偏置量。偏置位置所代表指的内容及其之后的内容即为此处内容。如何理解呢,比如www.stanford.com出现一次,第一个w在第0x10位,下次出现www.stanford.com则可表示为0xc010,如果出现了market.stanford.com,则market正常表示,后续为0xc014,0x14指向stanford开头。