Browsed by
标签: format

NAME、CNAME 格式

NAME、CNAME 格式

总体而言, 早期 DNS 协议是个比较简单的协议。受限于 UDP 大小和数据量, 基于 UDP 的 DNS 协议限制了包大小,并且采用二进制编码方式力求减少数据量占用。

二进制编码方式相比文本方式(例如HTTP、SIP、SMTP等)最明显的缺点就是不直观,再用一些技巧减少数据量,DNS 协议在定义、实现方面总显得有些弯弯绕绕。

比如 NAME、CNAME 等结构的编码。

本文记录了这些古怪的编码方式,方便以后查找,并帮助后续的开发者不会被代码给绕晕。作为我个人来说,还是尽快忘记这些吧。


方式一:纯压缩编码方式

这种方式应用很普遍,以“0xc0”标记开始,加上一个字节的 offset,进行消息包内的寻址即可。如下图所示:

DNS offset 编码
offset 方式编码

其中, 0x0c 就是偏移量。


方式二:直接编码方式

这种方式比较直接,占用数据量也相对大一些,将域名完整信息存在数据包中。如下图所示:

直接编码
直接编码方式

需要说明的是:并不是直接将所有字符存进去就 OK 了。对于域名数据,以“.”符号分割成几个单元,每个单元数据采用 “length + value” 方式进行编码,最后以0x00结束编码。以上述数据为例:

08 6e 73 69 6e 61 69 6d 67 04 67 73 6c 62 08 73
69 6e 61 65 64 67 65 03 63 6f 6d 00

比如,第一个 0x08,说明后面的“nsinaimg”(即 6e 73 69 6e 61 69 6d 67)长度;然后是 0x04,说明后面的“gslb”(即67 73 6c 62)长度……其他单元类推。


方式三: 混合编码方式

这种方式其实就是综合了上述两种方式。以直接编码方式开始,然后以压缩(偏移)编码方式结尾。如下图所示:

混合编码方式
混合编码方式

对图中的数据码流描述如下:

03 6b 6c 6e 04 67 72 69 64 c0 38

0x03 描述了“kln”(即 6b 6c 6e)的长度,0x04 描述了“grid”(即 67 72 69 64)的长度,而域名的后续部分,通过“c0 38”编码可以知道:需要偏移0x38字节获取。