域名系统(DNS)是一种用于TCP/IP应用程序的分布式数据库,它提供主机名字和IP地址之间的转换及有关电子邮件的选路信息。这里提到的分布式是指在Internet上的单个站点不能拥有所有的信息。每个站点(如大学中的系、校园、公司或公司中的部门)保留它自己的信息数据库,并运行一个服务器程序供Internet上的其他系统(客户程序)查询。DNS提供了允许服务器和客户程序相互通信的协议。
从应用的角度上看,对DNS的访问是通过一个地址解析器(resolver)来完成的。在Unix主机中,该解析器主要是通过两个库函数gethostbyname和gethostbyaddr来访问的,它们在编译应用程序时与应用程序连接在一起。前者接收主机名字返回IP地址,而后者接收IP地址来寻找主机名字。解析器通过一个或多个名字服务器来完成这种相互转换。
解析器并不像TCP/IP协议那样是操作系统的内核。在一个应用程序请求TCP打开一个连接或使用UDP发送一个数据报之前。心须将一个主机名转换为一个IP地址。操作系统内核中的TCP/IP协议族对于DNS一点都不知道。
DNS 基础
DNS的名字空间和Unix的文件系统相似,也具有层次结构,是一个树形结构。
每个结点有一个至多63个字符长的标识。这颗树的树根是没有任何标识的特殊结点。命名标识中一律不区分大写和小写。命名树上任何一个结点的域名就是将从该结点到最高层的域名串连起来,中间使用一个点“.”分隔这些域名(注意这和Unix文件系统路径的形成不同,文件路径是由树根依次向下的形成的)。域名树中的每个结点必须有一个唯一的域名,但域名树中的不同结点可使用相同的标识。
以点“.”结尾的域名称为绝对域名或完全合格的域名FQDN(Full Qualified DomainName),例如sun.tuc.noao.edu.。如果一个域名不以点结尾,则认为该域名是不完全的。如何使域名完整依赖于使用的DNS软件。如果不完整的域名由两个或两个以上的标号组成,则认为它是完整的;或者在该域名的右边加入一个局部后缀。例如域名sun通过加上局部后缀.tuc.noao.edu.成为完整的。
顶级域名被分为三个部分:
- arpa是一个用作地址到名字转换的特殊域。
- 7个3字符长的普通域。有些书也将这些域称为组织域。
- 所有2字符长的域均是基于ISO3166中定义的国家代码,这些域被称为国家域,或地理域。
7个普通域的正式划分:
域 | 描述 |
---|---|
com | 商业机构 |
edu | 教育机构 |
gov | 其他美国政府部门 |
int | 国际组织 |
mil | 美国军事网点 |
net | 网络 |
org | 其他组织 |
在DNS中,通常认为3字符长的普通域仅用于美国的组织机构,2字符长的国家域则用国际组织美国军事网点于每个国家,但情况并不总是这样。许多非美国的组织机构仍然使用普通域,而一些美国的其他组织组织机构也使用.us的国家域。普通域中只有.gov和.mil域局限于美国。
许多国家将它们的二级域组织成类似于普通域的结构:例如,.ac.uk是英国研究机构的二级域名,.co.uk则是英国商业机构的二级域名。
没有哪个机构来管理域名树中的每个标识,相反,只有一个机构,即网络信息中心NIC负责分配顶级域和委派其他指定地区域的授权机构。
一个独立管理的DNS子树称为一个区域(zone)。一个常见的区域是一个二级域,如noao.edu。许多二级域将它们的区域划分成更小的区域。例如,大学可能根据不同的系来划分区域,公司可能根据不同的部门来划分区域。
一旦一个区域的授权机构被委派后,由它负责向该区域提供多个名字服务器。当一个新系统加入到一个区域中时,该区域的DNS管理者为该新系统申请一个域名和一个IP地址,并将它们加到名字服务器的数据库中。这就是授权机构存在的必要性。例如,在一个小规模的大学,一个人就能完成每次新系统的加入。但对一个规模较大的大学来说,这一工作必须被专门委派的机构(可能是系)来完成,因为一个人已无法维持这一工作。
一个名字服务器负责一个或多个区域。一个区域的管理者必须为该区域提供一个主名字服务器和至少一个辅助名字服务器。主、辅名字服务器必须是独立和冗余的,以便当某个名字服务器发生故障时不会影响该区域的名字服务。
主、辅名字服务器的主要区别在于主名字服务器从磁盘文件中调入该区域的所有信息,而辅名字服务器则从主服务器调入所有信息。我们将辅名字服务器从主服务器调入信息称为区域传送。
当一个新主机加入一个区域时,区域管理者将适当的信息(最少包括名字和IP地址)加入到运行在主名字服务器上的一个磁盘文件中,然后通知主名字服务器重新调入它的配置文件。辅名字服务器定时(通常是每隔3小时)向主名字服务器询问是否有新数据。如果有新数据,则通过区域传送方式获得新数据。
当一个名字服务器没有请求的信息时,它将如何处理?它必须与其他的名字服务器联系。(这正是DNS的分布特性)。然而,并不是每个名字服务器都知道如何同其他名字服务器联系。相反,每个名字服务器必须知道如何同根的名字服务器联系。1993年4月时有8个根名字服务器,所有的主名字服务器都必须知道根服务器的IP地址(这些IP地址在主名字服务器的配置文件中,主服务器必须知道根服务器的IP地址,而不是它们的域名)。根服务器则知道所有二级域中的每个授权名字服务器的名字和位置(即IP地址)。这意味着这样一个反复的过程:正在处理请求的名字服务器与根服务器联系,根服务器告诉它与另一个名字服务器联系。
DNS的一个基本特性是使用超高速缓存。即当一个名字服务器收到有关映射的信息(主机名字到IP地址)时,它会将该信息存放在高速缓存中。这样若以后遇到相同的映射请求,就能直接使用缓存中的结果而无需通过其他服务器查询。
DNS 的报文格式
这个报文由12字节长的首部和4个长度可变的字段组成。
标识字段由客户程序设置并由服务器返回结果。客户程序通过它来确定响应与查询是否匹配。
16 bit的标志字段被划分为若干子字段,从最左位开始依次介绍各子字段:
- 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个16 bit字段说明最后4个变长字段中包含的条目数。对于查询报文,问题(question)数通常是1,而其他3项则均为0。类似地,对于应答报文,回答数至少是1,剩下的两项可以是0或非0。
DNS 查询报文中的问题部分
问题部分的每个问题的格式如下,通常只有一个问题。
查询名是要查找的名字,它是一个或多个标识符的序列。每个标识符以首字节的计数值来说明随后标识符的字节长度,每个名字以最后字节为0结束,长度为0的标识符是根标识符。计数字节的值必须是0~63的数,因为标识符的最大长度仅为63(计数字节的最高两比特为1,即值192~255,将用于压缩格式)。不像我们已经看到的许多其他报文格式,该字段无需以整32 bit边界结束,即无需填充字节。
每个问题有一个查询类型,而每个响应(也称为一个资源记录)也有一个类型。大约有20个不同的类型值,其中的一些目前已经过时。查询类型是类型的一个超集(superset):表中显示的类型值中只有两个能用于查询类型。
名字 | 数值 | 描述 | 类型? | 查询类型? |
---|---|---|---|---|
A | 1 | IP地址 | * | * |
NS | 2 | 名字服务器 | * | * |
CNAME | 5 | 规范名字 | * | * |
PTR | 12 | 指针记录 | * | * |
HINFO | 13 | 主机信息 | * | * |
MX | 15 | 邮件交换信息 | * | * |
AXFR | 252 | 对区域转换的请求 | * | |
*或ANY | 255 | 对所有记录的请求 | * |
最常用的查询类型是A类型,表示期望获得查询名的IP地址。一个PTR查询则请求获得一个IP地址对应的域名。这是一个指针查询。
查询类通常是1,指互联网地址(某些站点也支持其他非IP地址)。
DNS 响应报文中的资源记录部分
DNS报文中最后的三个字段,回答字段、授权字段和附加信息字段,均采用一种称为资源记录RR(Resource Record)的相同格式。资源记录的格式如下:
域名是记录中资源数据对应的名字。它的格式和前面介绍的查询名字段格式相同。
类型说明RR的类型码。它的值和前面介绍的查询类型值是一样的。类通常为1,指Internet数据。
生存时间字段是客户程序保留该资源记录的秒数。资源记录通常的生存时间值为2天。
资源数据长度说明资源数据的数量。该数据的格式依赖于类型字段的值。对于类型1(A记录)资源数据是4字节的IP地址。
指针查询
DNS中一直难于理解的部分就是指针查询方式,即给定一个IP地址,返回与该地址对应的域名。
查看一下顶级域arpa,及它下面的in-addr域。当一个组织加入Internet,并获得DNS域名空间的授权,如noao.edu,则它们也获得了对应IP地址的in-addr.arpa域名空间的授权。在noao.edu这个例子中,它是网络号为140.252的B类网络。在DNS树中结点in-addr.arpa的下一级必须是该IP地址的第一字节(140),再下一级为该IP地址的下一个字节(252),依此类推。但应牢记的是DNS名字是由DNS树的底部逐步向上书写的。这意味着对于IP地址为140.252.13.33的sun主机,它的DNS名字为33.13.252.140.in-addr.arpa。
必须写出4字节的IP地址,因为授权的代表是基于网络号:A类地址是第一字节,B类地址是第一、二字节,C类地址则是第一、二、三字节。IP地址的第一字节一定位于in-addr的下一级,但FQDN却是自树底往上书写的。如果FQDN由顶往下书写,则这个IP地址的DNS名字将是arpa.in-addr.140.252.13.33,而它所对应的域名将是edu.noao.tuc.sun。
如果DNS树中没有独立的分支来处理这种地址—名字的转换,将无法进行这种反向转换,除非从树根开始依次尝试每个顶级域。毫不夸张地说,这将需要数天或数周的时间。虽然反写IP地址和特殊的域名会造成某些混乱,但in-addr解决方案仍是一种最有效的方式。
只有在使用host程序或tcpdump程序直接同DNS打交道时,才会担心in-addr域和反写IP地址影响我们。从应用的角度上看,正常的名字解析器函数(gethostbyaddr)将接收一个IP地址并返回对应主机的有关信息。反转这些字节和添加in-addr.arpa域均由该函数自动完成。
主机名检查
当一个IP数据报到达一个作为服务器的主机时,无论是UDP数据报还是TCP连接请求,服务器进程所能获得的是客户的IP地址和端口号(UDP或TCP)。某些服务器需要客户的IP地址来获得在DNS中的指针记录。
其他的一些服务器如Rlogin服务器不但需要客户的IP地址来获得指针记录,还要向DNS询问该IP地址所对应的域名,并检查返回的地址中是否有地址与收到的数据报中的源IP地址匹配。该检查是因为.rhosts文件中的条目仅包含主机名,而没有IP地址,因此主机需要证实该主机名是否对应源IP地址。
某些厂商将该项检查自动并入其名字解析器的例程中,特别是函数gethostbyaddr。这使得任何使用名字解析器的程序均可获得这种检查,而无需在应用中人为地进行这项检查。
资源记录
至今我们已经见到了一些不同类型的资源记录(RR):IP地址查询为A类型,指针查询为类型PTR。也已看到了由名字服务器返回的资源记录:回答RR、授权RR和附加信息RR。
类型 | 介绍 |
---|---|
A | 一个A记录定义了一个IP地址,它存储32 bit的二进制数。 |
PTR | 指针记录用于指针查询。 IP地址被看作是in-addr.arpa域下的一个域名(标识符串)。 |
CNAME | 这表示“规范名字 (canonical name)”。它用来表示一个域名(标识符串),而有规范名字的域名通常被称为别名 (alias)。某些FTP服务器使用它向其他的系统提供一个易于记忆的别名。 |
HINFO | 表示主机信息:包括说明主机CPU和操作系统的两个字符串。并非所有的站点均提供它们系统的HINFO记录,并且提供的信息也可能不是最新的。 |
MX | 邮件交换记录 |
NS | 名字服务器记录。它说明一个域的授权名字服务器。它由域名表示(符号串)。 |
邮件交换记录,用于以下一些场合:(1)一个没有连到Internet的站点能将一个连到Internet的站点作为它的邮件交换器。这两个站点能够用一种交替的方式交换到达的邮件,而通常使用的协议是UUCP协议。(2)MX记录提供了一种将无法到达其目的主机的邮件传送到一个替代主机的方式。(3)MX记录允许机构提供供他人发送邮件的虚拟主机,如cs.university.edu,即使这样的主机名根本不存在。(4)防火墙网关能使用MX记录来限制外界与内部系统的连接。许多不能与Internet连接的站点通过UUCP链路与一个连接在Internet上的站点如UUNET相连接。通过MX记录能使用user@host这种邮件地址向那个站点发送电子邮件。
高速缓存
为了减少Internet上DNS的通信量,所有的名字服务器均使用高速缓存。在标准的Unix实现中,高速缓存是由名字服务器而不是由名字解析器维护的。既然名字解析器作为每个应用的一部分,而应用又不可能总处于工作状态,因此将高速缓存放在只要系统(名字服务器)处于工作状态就能起作用的程序中显得很重要。这样任何一个使用名字服务器的应用均可获得高速缓存。在该站点使用这个名字服务器的任何其他主机也能共享服务器的高速缓存。
用UDP还是TCP
注意到DNS名字服务器使用的熟知端口号无论对UDP还是TCP都是53。这意味着DNS均支持UDP和TCP访问。那么这两种协议都在什么情况下采用以及采用的理由都是什么呢?
当名字解析器发出一个查询请求,并且返回响应中的TC(删减标志)比特被设置为1时,它就意味着响应的长度超过了512个字节,而仅返回前512个字节。在遇到这种情况时,名字解析器通常使用TCP重发原来的查询请求,它将允许返回的响应超过512个字节。既然TCP能将用户的数据流分为一些报文段,它就能用多个报文段来传送任意长度的用户数据。
此外,当一个域的辅助名字服务器在启动时,将从该域的主名字服务器执行区域传送。我们也说过辅助服务器将定时(通常是3小时)向主服务器进行查询以便了解主服务器数据是否发生变动。如果有变动,将执行一次区域传送。区域传送将使用TCP,因为这里传送的数据远比一个查询或响应多得多。
既然DNS主要使用UDP,无论是名字解析器还是名字服务器都必须自己处理超时和重传。此外,不像其他的使用UDP的Internet应用(TFTP、BOOTP和SNMP),大部分操作集中在局域网上,DNS查询和响应通常经过广域网。分组丢失率和往返时间的不确定性在广域网上比局域网上更大。这样对于DNS客户程序,一个好的重传和超时程序就显得更重要了。
小结
DNS是任何与Internet相连主机必不可少的一部分,同时它也广泛用于专用的互联网。层次树是组成DNS域名空间的基本组织形式。
应用程序通过名字解析器将一个主机名转换为一个IP地址,也可将一个IP地址转换为与之对应的主机名。名字解析器将向一个本地名字服务器发出查询请求,这个名字服务器可能通过某个根名字服务器或其他名字服务器来完成这个查询。
所有的DNS查询和响应都有相同的报文格式。这个报文格式中包含查询请求和可能的回答资源记录、授权资源记录和附加资源记录。