DNS 协议

DNS资源记录(RR)

在介绍DNS层协议之前,先了解一下DNS服务器存储的资源记录(Resource Records,RRs),一条资源记录(RR)记载着一个映射关系。每条RR通常包含如下表所示的一些信息:

字段	含义
NAME	名字
TYPE	类型
CLASS	类
TTL	生存时间
RDLENGTH	RDATA所占的字节数
RDATA	数据


NAME和RDATA表示的含义根据TYPE的取值不同而不同,常见的:
若TYPE=A,则name是主机名,value是其对应的ip;
若TYPE=NS,则name是一个域,value是一个权威DNS服务器的主机名。该记录表示name域的域名解析将由value主机名对应的DNS服务器来做;
若TYPE=CNAME,则value是别名为name的主机对应的规范主机名;
若TYPE=MX,则value是别名为name的邮件服务器的规范主机名;
……

TYPE实际上还有其他类型,所有可能的type及其约定的数值表示如下:

TYPE	value	meaning
A	1	a host address
NS	2	an authoritative name server
MD	3	a mail destination (Obsolete - use MX)
MF	4	a mail forwarder (Obsolete - use MX)
CNAME	5	the canonical name for an alias
SOA	6	marks the start of a zone of authority
MB	7	a mailbox domain name (EXPERIMENTAL)
MG	8	a mail group member (EXPERIMENTAL)
MR	9	a mail rename domain name (EXPERIMENTAL)
NULL	10	a null RR (EXPERIMENTAL)
WKS	11	a well known service description
PTR	12	a domain name pointer
HINFO	13	host information
MINFO	14	mailbox or mail list information
MX	15	mail exchange
TXT	16	text strings

DNS请求

DNS请求与响应的格式是一致的,其整体分为Header、Question、Answer、Authority、Additional5部分,如下图所示:

_Header

Header部分是一定有的,长度固定为12个字节;其余4部分可能有也可能没有,并且长度也不一定,这个在Header部分中有指明。Header的结构如下:

下面说明一下各个字段的含义:

ID:占16位。该值由发出DNS请求的程序生成,DNS服务器在响应时会使用该ID,这样便于请求程序区分不同的DNS响应。
QR:占1位。指示该消息是请求还是响应。0表示请求;1表示响应。
OPCODE:占4位。指示请求的类型,有请求发起者设定,响应消息中复用该值。0表示标准查询;1表示反转查询;2表示服务器状态查询。3~15目前保留,以备将来使用。
AA(Authoritative Answer,权威应答):占1位。表示响应的服务器是否是权威DNS服务器。只在响应消息中有效。
TC(TrunCation,截断):占1位。指示消息是否因为传输大小限制而被截断。
RD(Recursion Desired,期望递归):占1位。该值在请求消息中被设置,响应消息复用该值。如果被设置,表示希望服务器递归查询。但服务器不一定支持递归查询。
RA(Recursion Available,递归可用性):占1位。该值在响应消息中被设置或被清除,以表明服务器是否支持递归查询。
Z:占3位。保留备用。
RCODE(Response code):占4位。该值在响应消息中被设置。取值及含义如下:
0:No error condition,没有错误条件;
1:Format error,请求格式有误,服务器无法解析请求;
2:Server failure,服务器出错。
3:Name Error,只在权威DNS服务器的响应中有意义,表示请求中的域名不存在。
4:Not Implemented,服务器不支持该请求类型。
5:Refused,服务器拒绝执行请求操作。
6~15:保留备用。
QDCOUNT:占16位(无符号)。指明Question部分的包含的实体数量。
ANCOUNT:占16位(无符号)。指明Answer部分的包含的RR(Resource Record)数量。
NSCOUNT:占16位(无符号)。指明Authority部分的包含的RR(Resource Record)数量。
ARCOUNT:占16位(无符号)。指明Additional部分的包含的RR(Resource Record)数量。

如下:

import * as dns from 'dns';

var server = new dns.Resolver();
server.setServers(['127.0.0.1:5553']);
server.resolve('google.com', 'A', (err, addresses) => {
    console.log(err);
    console.log(addresses);
});

============= connected <<<< 127.0.0.1:36336 =============
ArrayBuffer {
  [Uint8Contents]: <bd e7 01 00 00 01 00 00 00 00 00 00 06 67 6f 6f 67 6c 65 03 63 6f 6d 00 00 01 00 01>,
  byteLength: 28
}

该例子中,一个A查询:

                                                       |-> Header部分结束
                                                       |
<bd e7,    01 00,     00 01,      00 00,00 00,00 00,     06 67 6f 6f 67 6c 65 03 63 6f 6d 00, 00 01, 00 01>
  ID                Question数量     .....其它数量为0           ?  g  o  o  g  l  e  ?  c  o  m

Question

Question部分的每一个实体的格式如下图所示:

QNAME:字节数不定,以0x00作为结束符。表示查询的主机名。注意:众所周知,主机名被"."号分割成了多段标签。在QNAME中,每段标签前面加一个数字,表示接下来标签的长度。比如:api.sina.com.cn表示成QNAME时,会在"api"前面加上一个字节0x03,"sina"前面加上一个字节0x04,"com"前面加上一个字节0x03,而"cn"前面加上一个字节0x02;
QTYPE:占2个字节。表示RR类型,见以上RR介绍;
QCLASS:占2个字节。表示RR分类,见以上RR介绍。

Answer

Answer、Authority、Additional部分格式一致,每部分都由若干实体组成,每个实体即为一条RR,之前有过介绍,格式如下图所示:

NAME:长度不定,可能是真正的数据,也有可能是指针(其值表示的是真正的数据在整个数据中的字节索引数),还有可能是二者的混合(以指针结尾)。若是真正的数据,会以0x00结尾;若是指针,指针占2个字节,第一个字节的高2位为11。
TYPE:占2个字节。表示RR的类型,如A、CNAME、NS等,见以上RR介绍;
CLASS:占2个字节。表示RR的分类,见以上RR介绍;
TTL:占4个字节。表示RR生命周期,即RR缓存时长,单位是秒;
RDLENGTH:占2个字节。指定RDATA字段的字节数;
RDATA:即之前介绍的value,含义与TYPE有关,见以上RR介绍。

一个正常的响应如下:

var msg = [0x48, 0xc3, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x02, 0x00, 0x01];

var udp4 = udp.createSocket('udp4');
udp4.send(Buffer.from(msg), 53, '1.1.1.1', (error, bytes) => {
    error && console.error(error);
    console.log({ bytes });
    udp4.on('message', (msg, rinfo) => {
        console.log(rinfo);
        console.log(msg.buffer);
    })
});

{ address: '1.1.1.1', family: 'IPv4', port: 53, size: 100 }
ArrayBuffer {
  [Uint8Contents]: <48 c3 81 80 00 01 00 04 00 00 00 00 06 67 6f 6f 67 6c 65 03 63 6f 6d 00 00 02 00 01 c0 0c 00 02 00 01 00 05 43 c1 00 06 03 6e 73 32 c0 0c c0 0c 00 02 00 01 00 05 43 c1 00 06 03 6e 73 31 c0 0c c0 0c 00 02 00 01 00 05 43 c1 00 06 03 6e 73 33 c0 0c c0 0c 00 02 00 01 00 05 43 c1 00 06 03 6e 73 34 c0 0c>,
  byteLength: 100
}

解析:

48 c3 81 80 00 01 00 04 00 00 00 00 06 67 6f 6f 67 6c 65 03 63 6f 6d 00 00 02 00 01 c0 0c 00 02 00 01 00 05 43 c1 00 06 03 6e 73 32 c0 0c c0 0c 00 02 00 01 00 05 43 c1 00 06 03 6e 73 31 c0 0c c0 0c 00 02 00 01 00 05 43 c1 00 06 03 6e 73 33 c0 0c c0 0c 00 02 00 01 00 05 43 c1 00 06 03 6e 73 34 c0 0c

See

https://www.cnblogs.com/dongkuo/p/6714071.html

posted @ 2021-01-31 02:43  develon  阅读(629)  评论(0编辑  收藏  举报