DNS协议的客户端实现

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

 

1、rfc版本

我先附上主要参考的rfc版本http://www.ietf.org/rfc/rfc1035.txt

 

2、研究过程

使用wireshark跟踪port 53端口,然后ping www.csdn.net记录下发送和接收的报文。

 

3、解码代码

$(wireshark_src)/epan/dissectors/packet-dns.c 中dns_get_name函数

 

 

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

 

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

 

在填充和解析报文的时候,必须注意,这里报文所有的数据格式都是大端格式,而且协议描述的flag部分非常容易出错,必须予以强调。

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

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

 

HEADER中的QDCOUNT只是question节的数量,ANCOUNT为answer节的数量,NSCOUNT为auth节的数量,ARCOUNT为addition节的数量。这几个2字节构成的整型也是大端格式。

 

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

一般来说QTYPE如果是域名解析的话,为T_A =1 ,当然也有T_MX(mail exchange)。在所以名称字段,比较特殊,比如这里的QNAME,其他以字符串形式出现的都是一样的规则。

比如www.csdn.net,他会编成这样的形式:

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的几个报文格式都是一样:

 

只需要关注的是,每个TYPE都会有自己格式填充在RDATA中,RDATA实际上存放的是一个缓冲区。根据具体TYPE,来解析他的含义,一般说来,我们比较关注的A/CNAME/MX等格式,其他都可以忽略。

 

 

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

win32也有个函数,不过也差不多。按道理ping应该会有相应的代码,可惜我没有找到相关。最紧密的是gethostbyname,似乎不能解析吧,没深入研究。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值