zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    Kubernetes-一文详解ServiceAccount与RBAC权限控制
    删除无用的docker镜像与容器
    How do I write one to many query in Dapper.Net?
    c# 使用反射Reflection的Emit实现动态创建元数据及可执行文件
    IE浏览器下bootStrap form-control input输入框不显示兼容性问题
    WPF控件从一个窗口移动到另一个窗口,特别适合实时刷新的
    添加/扫描显示二维码中的换行之【另类视野】
    各浏览器官方离线版下载地址
    CentOS挂载NTFS
    System.Data.SQLite.Core for .NET 5 Core manual reference
  • 原文地址:https://www.cnblogs.com/develon/p/14351482.html
Copyright © 2011-2022 走看看