DNS协议以及报文格式总结
主要参考内容为RFC 1034、1035(简略参考,需要时再去阅读)还有以下博客参考
本文只是简略总结学习DNS协议的要点。
DNS协议思想
总结下来就是核心是分层式的思想。有以下几个点:
-
分层式结构自然引出树结构,树的每一个父节点只负责管理子节点的信息。
-
节点的表示引出域名概念,按照RFC文档的规定,域名是0-63个字节的在指定字符范围内的标签,其中最特殊的0个字节缺省为根节点专属的域名。
-
最终的主机名,是一个从根节点到达叶节点的自顶向下路径,并且路径上相邻父子节点之间通过.分隔,形成对人类友好的字符串形式。
-
在DNS报文中,主机名将其中的点号分割替换为,通过表明域名长度的数字分割。显然结尾是0,以表示到达根节点,在此也可以看出,利用NULL作为根节点表示,是为了方便DNS报文中表示主机名结尾。
-
域名服务器,是域名父节点管理其子节点信息的实际执行者。一般分为根服务器,顶级域名服务器,权威服务器
而DNS协议解析,根据RFC 1034的说法,是通过resolver完成的,实际上过程是这样的。
- 对于迭代查询:
- 客户端选择代理服务器,让他完成所有查询任务。
- DNS代理服务器完成如下操作,以下为比喻。
- DNS代理服务器中预先有根服务器主机名以及其IP地址,因此去到根节点上,在已知需要解析的主机名,因此,我可以推断出下一级的域名,也就是下一个要去子节点的标签,而当前根节点具有的恰好就是所有他管理的子节点信息。
- 子节点信息主要是,子节点的主机名是什么?子节点的IP地址是什么?这解决了是谁,在哪里的问题。
- 之后代理服务器就跑去这个查出来的子节点,这时候,根据树是递归定义出来的,当前的节点到达我想到达的最终主机之间又可以看作一棵树,那么我就还让代理服务器按照先前的方式不断地问,知道遇到了叶子节点IP地址。
- 此时,代理服务器完成任务,就把查出来的IP地址返回给客户端。
- 对于递归查询:
- 客户端选择代理服务器,让他完成所有查询任务。
- DNS代理服务器完成如下操作,以下为比喻。
- 此时,查询就像一个甩锅的过程,先前除了代理服务器,所有服务器都是询问-回答的状态,而递归查询则是,代理服务器把查询任务丢给了根服务器,根服务器认出这是递归查询,就跑到有这个需要解析的路径分析出的子节点所在处(事实上,他只知道他的子节点,他查询时候能管的也只有他的子节点),把任务丢给子节点,然后,就静静等待子节点完成交差,等到子节点完成后,就把这个最终的结果还给代理服务器。
- 每一级都是如此,把任务甩给下一节点,静静等待下一节点完成后,在还给之前给自己指派任务的服务器,也可以理解为,每一个下一节点的DNS服务器,都被当作了一个代理服务器。
每次这么来一遍,效率很低,考虑到现实中一个地址可能要问好几次,比如,学生选课,期间,选课官网在一段时间内,肯定是高频访问,那么如果代理服务器有存储先前的结果,那就不必大费周章的从头推导,直接背书完了。当然了,每次都要有新知识的流入,比如过一段时间,LOL S赛直播,整个大学就开始需要直播间的地址,所以,就得忘掉旧知识,不然屯的都是旧知识,没有把新知识背住,新知识用起来就很麻烦。这就是DNS服务器缓存服务器的概念,以及TTL的由来。
DNS报文格式
因特网的协议,重要特色就是报文格式,格式化的交流方式,才可以使得因特网够高效稳定。
头部
- 会话标识(2 bytes):请求报文与对应的应答报文整个是相同的,区分应答是针对哪一个询问。
- 标志(2 bytes):是一个标准的bit-wise的标识方法,每一位的意义如下
- QR (1 BIT): 查询对应0,响应为1
- opcode(4 bits): 0-标准查询,1-反向查询,2-服务器状态请求
- AA(1 BIT): 授权回答
- TC(1 BIT): 可截断
- RD(1bit):表示期望递归。
- RA(1bit):表示可用递归。
- Z(3 bits): 全0
- rcode(4 bits): 应答,类似http的404,200之类的。
- 0 没有错误。
- 1 报文格式错误(Format error) - 服务器不能理解请求的报文。
- 2 服务器失败(Server failure) - 因为服务器的原因导致没办法处理这个请求。
- 3 名字错误(Name Error) - 只有对授权域名解析服务器有意义,指出解析的域名不存在。
- 4 没有实现(Not Implemented) - 域名服务器不支持查询类型。
- 5 拒绝(Refused) - 服务器由于设置的策略拒绝给出应答。比如,服务器不希望对某些请求者给出应答,或者服务器不希望进行某些操作(比如区域传送zone transfer)。
- 6:本来应该没有的域名,但是有
- 7:有一个资源记录集存在,本来不应该有
- 8:有一个资源记录集应该有,但它没有
- 9:查询的服务器并不权威
- 10:相关的信息并不是当前域存在的
- 数量字段,协议报文经常出现的部分。Questions、Answer RRs、Authority RRs、Additional RRs 各自表示后面的四个区域的数目。Questions表示查询问题区域节的数量,Answers表示回答区域的数量,Authoritative namesversers表示授权区域的数量,Additional recoreds表示附加区域的数量。
正文
分为Queries 和 RR部分
Queries
-
查询名NAME: 长度不固定,一般是需要查询的主机名(uestc.edu.cn诸如此类),如果是反向查询,就是IP地址。格式如前所述,一个字节的数字标识域名的长度,并将整个主机名分割。
-
查询类型,这是由RFC定义的RR 类型,起初只定义了一部分,随着IPV6等问题,在之后的RFC文档又定义了新的类型
类型 | 助记符 | 说明 |
---|---|---|
1 | A | 由域名获得IPv4地址 |
2 | NS | 查询域名服务器 |
5 | CNAME | 查询规范名称 |
6 | SOA | 开始授权 |
11 | WKS | 熟知服务 |
12 | PTR | 把IP地址转换成域名 |
13 | HINFO | 主机信息 |
15 | MX | 邮件交换 |
28 | AAAA | 由域名获得IPv6地址 |
252 | AXFR | 传送整个区的请求 |
255 | ANY | 对所有记录的请求 |
- 查询类:有chaos,internet,通常选internet,用1表示
资源记录
包含回答,授权,附加三个区域,格式一致。其中回答是对询问的响应,授权是权威服务器端信息,附加是可能有用的信息。
格式如下
- 既然是对于回答的应答,那也该有对应,所以按照此思路设计
- 域名:一种方式就是同Queries所陈述的一样,但是,出现重复的情况,我们可以设置一个指针指向那个域名,节省空间。这种偏移指针的方式,长度为两字节,最高两位指定为11后,就能识别这是一个偏移指针,剩下14位就用于指出偏移地址,以DNS报文开头为0
- 对应Queries的有查询类型,查询类
- 生存时间(TTL):这就是之前提到的为了缓存服务器而设置的。
- 资源数据:前面铺垫这么多,就需要干货了。如果查询要的是A型RR,那就返回IPV4地址,是一个CNAME的RR,那就返回一个规范主机名。