ping dns服务器,分析其协议内容,DNS协议分析

本文详细介绍了DNS协议的工作原理及其实现过程。包括DNS报文的格式解析、使用Wireshark进行跟踪分析的方法,以及常见DNS请求类型的解析技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

DNS

是域名解析协议,服务端实现很多,不过很多时候我需要的客户端程序。用dns来解析IP在很多地方都会,他很重要,但经常被刻意的忽略。这里记录一些我自

己实现dns客户端的一些资料和过程。

1、

rfc版本

我先附上主要参考的rfc版本。

2、研究过程

使用wireshark跟踪port 53端口,然后ping

记录下发送和接收的报文。

3、解码代码

$(wireshark_src)\epan\dissectors\packet-dns.c

中dns_get_name函数

所有的

DNS,不论是发送和接收到,都遵循相同的消息格式,如

/* MESSAGE FORMAT*/

/*

+---------------------+

|        Header       |

+---------------------+

|       Question      | the question for the name server

+---------------------+

|        Answer       | RRs answering the question

+---------------------+

|      Authority      | RRs pointing toward an authority

+---------------------+

|      Additional     | RRs holding additional information

+---------------------+

*/

其中消息头部的格式比较固定,如下:

/* HEADER FORMAT*/

/*

1  1  1  1  1  1

0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

|                      ID                       |

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

|QR|   Opcode  |AA|TC|RD|RA|   Z    |   RCODE   |

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

|                    QDCOUNT                    |

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

|                    ANCOUNT                    |

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

|                    NSCOUNT                    |

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

|                    ARCOUNT                    |

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

*/

在填充和解析报文的时候,必须注意,这里报文所有的数据

格式都是大端格式,而且协议描述的flag部分非常容易出错,必须予以强调。

假设QR=1,其他为0,那么这个字节的值为0x80;如果RD=1,而其他为0,那么这个字节的值为0x01。我们假

设QR字段到RCODE字段的这两个字节中,QR=1,RD=1,RC=1,其他部分都是0,那么这2个字节的值为0x81 , 0x80。

16bit的标志字段 如下:

QR:0

表示查询报文,1表示响应报文

Opcode:通常值为0(标准查询),其他值为1(反向查询)和2(服务器状态请求)。

AA:表示授权回

答(authoritative answer).

TC:表示可截断的(truncated)

RD:表示期望递归

RA:表示可用

递归

随后3bit必须为0

Rcode:返回码,通常为0(没有差错)和3(名字差错)

后面4个16bit字段说明最后4个变长字

段中包含的条目数。

仔细理解

上面这段描述,才能理解各个标志位的含义。

HEADER

中的QDCOUNT只是question节的数量,ANCOUNT为answer节的数量,NSCOUNT为auth节的数量,ARCOUNT为

addition节的数量。这几个2字节构成的整型也是大端格式。

question主要是由客户端请求来填的,他的格式为

/* QUESTION FORMAT */

/*

1  1  1  1  1  1

0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

|                                               |

/                     QNAME                     /

/                                               /

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

|                     QTYPE                     |

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

|                     QCLASS                    |

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

*/

一般来说QTYPE如果是域名解析的话,为T_A =1

,当然也有T_MX(mail exchange)。在所以名称字段,比较特殊,比如这里的QNAME,其他以字符串形式出现的都是一样的规则。

比如,他会编成这样的形式:

0x03 0x77 0x77 0x77  0x04

0x63 0x73 0x64 0x6e 0x03 0x6e 0x65 0x74 0x00

和其他字符串一样,这个格式仍然以0x00结尾,不过中间确实不同,他是len +

data来混合编码,每个字符串都是以长度开始,然后接着内容。比如"www",他的字符值为0x77 ,

在前头是0x03开始,表示后面紧跟着3个字符。

还有一种格式,是使用指针,准确地说应该是偏移量,如下:

0xc0 0x0c 0x00 0x01 0x00 0x01 0x00 0x00 0x02 0x1a 0x00

0x04

这个是DNS服务端返回报文中地一

段。0xc0开头,表示这个是指针,后面字节跟着地是偏移量。这个偏移量应该是这样计算的:0xc0 &

(~0xc0),这样得到偏移量的高字节,然后和0x0c拼接成一个大端格式短整型。这偏移量是相对于报文起点的偏移量。

我打个比方,比如偏移量超过256,是300

,他的小端格式为0x012c,那么他在内存中的印象应该是这样的:

0xc1 0x2c。

ANSWER/AUTH/ADDS的几个报文格式都是一样:

/* ANSWER/AUTH/ADDI FORMAT */

/*

1  1  1  1  1  1

0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

|                                               |

/                                               /

/                      NAME                     /

|                                               |

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

|                      TYPE                     |

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

|                     CLASS                     |

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

|                      TTL                      |

|                                               |

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

|                   RDLENGTH                    |

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|

/                     RDATA                     /

/                                               /

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

*/

只需要关注的是,每个TYPE都会有自己格式填充在

RDATA中,RDATA实际上存放的是一个缓冲区。根据具体TYPE,来解析他的含义,一般说来,我们比较关注的A/CNAME/MX等格式,其他都可

以忽略。

linux下提供

res_query可以发送请求报文,但返回内容却需要自己解析,没发意思,跟自己写个库都差不多了。解析部分可以参看wireshark,做的很全。

win32也有个函数,不过也差不多。按道理ping应

该会有相应的代码,可惜我没有找到相关。最紧密的是gethostbyname,似乎不能解析吧,没深入研究。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值