概述
域名系统(DNS)是一种用于TCP/IP应用程序的分布式数据库,它提供主机名字和IP地址之间的转换及有关电子邮件的选路信息。
DNS提供了允许服务器和客户程序相互通信的协议。从应用的角度上看,对DNS的访问是通过一个地址解析器(resolver)来完成的。
DNS 基础
DNS的名字空间和Unix的文件系统相似,也具有层次结构。
下图展示了这种层次结构:

每个结点有一个至多 63个字符长的标识。这颗树的树根是没有任何标识的特殊结点。命名标识中一律不区分大写和小写。命名树上任何一个结点的域名就是将从该结点到最高层的域名串连起来,中间使用一个点“.”分隔这些域名域名树中的每个结点必须有一个唯一的域名,但域名树中的不同结点可使用相同的标识。
以点“ .”结尾的域名称为绝对域名或完全合格的域名 FQDN(Full Qualified Domain Name)。如果一个域名不以点结尾,则认为该域名是不完全的。如何使域名完整依赖于使用的DNS软件。如果不完整的域名由两个或两个以上的标号组成,则认为它是完整的;或者在该域名的右边加入一个局部后缀。
顶级域名被分为三个部分:
- arpa是一个用作地址到名字转换的特殊域
- 7个3字符长的普通域。有些书也将这些域称为组织域。
- 所有2字符长的域均是基于ISO3166中定义的国家代码,这些域被称为国家域,或地理域。
没有哪个机构来管理域名树中的每个标识,相反,只有一个机构,即网络信息中心NIC负责分配顶级域和委派其他指定地区域的授权机构。
一旦一个区域的授权机构被委派后,由它负责向该区域提供多个名字服务器。当一个新系统加入到一个区域中时,该区域的DNS管理者为该新系统申请一个域名和一个IP地址,并将它们加到名字服务器的数据库中。这就是授权机构存在的必要性。
一个名字服务器负责一个或多个区域。一个区域的管理者必须为该区域提供一个主名字服务器和至少一个辅助名字服务器。主、辅名字服务器必须是独立和冗余的,以便当某个名字服务器发生故障时不会影响该区域的名字服务。
主、辅名字服务器的主要区别在于主名字服务器从磁盘文件中调入该区域的所有信息,而辅名字服务器则从主服务器调入所有信息。我们将辅名字服务器从主服务器调入信息称为区域传送。
当一个新主机加入一个区域时,区域管理者将适当的信息(最少包括名字和IP地址)加入到运行在主名字服务器上的一个磁盘文件中,然后通知主名字服务器重新调入它的配置文件。辅名字服务器定时(通常是每隔 3小时)向主名字服务器询问是否有新数据。如果有新数据,则通过区域传送方式获得新数据。
DNS的一个基本特性是使用超高速缓存。即当一个名字服务器收到有关映射的信息(主机名字到IP地址)时,它会将该信息存放在高速缓存中。这样若以后遇到相同的映射请求,就能直接使用缓存中的结果而无需通过其他服务器查询。
DNS的报文格式
下图展示了DNS查询和响应的报文格式:

这个报文由12字节长的首部和4个长度可变的字段组成。
标识字段由客户程序设置并由服务器返回结果。客户程序通过它来确定响应与查询是否匹配。16bit的标志字段被划分为若干子字段,如图所示。

依次介绍各子字段:
- QR 是1bit字段:0表示查询报文,1表示响应报文。
- opcode是一个4bit字段:通常值为0(标准查询),其他值为1(反向查询)和2(服务器状态请求)。
- AA是1bit标志,表示“授权回答 (authoritative answer)”。该名字服务器是授权于该域的。
- TC是1bit字段,表示“可截断的 ( truncated )”。使用UDP时,它表示当应答的总长度超过512字节时,只返回前512个字节。
- RD是1bit字段表示“期望递归( recursion desired)”。该比特能在一个查询中设置,并在响应中返回。这个标志告诉名字服务器必须处理这个查询,也称为一个递归查询。如果该位为0,且被请求的名字服务器没有一个授权回答,它就返回一个能解答该查询的其他名字服务器列表,这称为迭代查询。
- RA是1bit字段,表示“可用递归”。如果名字服务器支持递归查询,则在响应中将该比特设置为1。
- 随后的3bit字段必须为0。
- rcode是一个4bit的返回码字段。通常的值为 0(没有差错)和 3(名字差错)。名字差错
只有从一个授权名字服务器上返回,它表示在查询中制定的域名不存在。
随后的 4个16bit 字段说明最后 4个变长字段中包含的条目数。对于查询报文,问题( question )数通常是 1,而其他3项则均为0。类似地,对于应答报文,回答数至少是 1,剩下的两项可以是0或非0。
DNS查询报文中的问题部分
DNS查询报文中问题部分的格式如图:

查询名是要查找的名字,它是一个或多个标识符的序列。每个标识符以首字节的计数值来说明随后标识符的字节长度,每个名字以最后字节为0结束,长度为0的标识符是根标识符。计数字节的值必须是0 ~ 63的数,因为标识符的最大长度仅为63。该字段无需以整 32bit边界结束,即无需填充字节。
每个问题有一个查询类型,而每个响应也有一个类型。大约有 20个不同的类型值,其中的一些目前已经过时。
下图显示了其中的一些值:

最常用的查询类型是 A类型,表示期望获得查询名的IP地址。一个PTR查询则请求获得一个IP地址对应的域名。这是一个指针查询
查询类通常是1,指互联网地址(某些站点也支持其他非 I P地址)。
DNS响应报文中的资源记录部分
DNS报文中最后的三个字段,回答字段、授权字段和附加信息字段,均采用一种称为资源记录RR(Resource Record)的相同格式。下图显示了资源记录的格式:

域名是记录中资源数据对应的名字。它的格式和前面介绍的查询名字段格式
类型说明RR的类型码。它的值和前面介绍的查询类型值是一样的。类通常为1,指Internet数据。
生存时间字段是客户程序保留该资源记录的秒数。资源记录通常的生存时间值为 2天。
资源数据长度说明资源数据的数量。该数据的格式依赖于类型字段的值。对于类型1(A记录)资源数据是4字节IP地址。
指针查询
DNS中一直难于理解的部分就是指针查询方式,即给定一个IP地址,返回与该地址对应的域名。
当一个组织加入Internet,并获得DNS域名空间的授权,则也获得了对应IP地址的in-addr.arpa域名空间的授权。在DNS树中结点in-addr.arpa的下一级必须是该IP地址的第一字节,再下一级为该IP地址的下一个字节,依此类推。牢记DNS名字是由DNS树的底部逐步向上书写的。
必须写出4字节的IP地址,因为授权的代表是基于网络号: A类地址是第一字节,B类地址是第一、二字节,C类地址则是第一、二、三字节。 IP地址的第一字节一定位于in-addr的下一级,但FQDN却是自树底往上书写的。
如果DNS树中没有独立的分支来处理这种地址—名字的转换,将无法进行这种反向转换,除非从树根开始依次尝试每个顶级域。这将需要数天或数周的时间。
高速缓存
为了减少Internet上DNS的通信量,所有的名字服务器均使用高速缓存。在标准的Unix实现中,高速缓存是由名字服务器而不是由名字解析器维护的。既然名字解析器作为每个应用的一部分,而应用又不可能总处于工作状态,因此将高速缓存放在只要系统(名字服务器)处于工作状态就能起作用的程序中显得很重要。这样任何一个使用名字服务器的应用均可获得高速缓存。在该站点使用这个名字服务器的任何其他主机也能共享服务器的高速缓存。
用UDP还是用TCP
注意到DNS名字服务器使用的熟知端口号无论对UDP还是TCP都是53。这意味着 DNS均支持UDP和TCP访问。
当名字解析器发出一个查询请求,并且返回响应中的TC(删减标志)比特被设置为1时,它就意味着响应的长度超过了512个字节,而仅返回前 512个字节。在遇到这种情况时,名字解析器通常使用TCP重发原来的查询请求,它将允许返回的响应超过 512个字节。既然TCP能将用户的数据流分为一些报文段,它就能用多个报文段来传送任意长度的用户数据。
此外,当一个域的辅助名字服务器在启动时,将从该域的主名字服务器执行区域传送。