DNS协议及C简单实现查询

DNS协议是互联网最重要的基础协议,也是用的最多的UDP协议之一,现在也开始支持基于TCP的DNS和基于ssl的加密的DNS协议。本文虫虫以一个简单实例带领大家一起学习DNS协议,实现一个简单的DNS查询客户端。DNS协议非常简单,详细可以参考国际互联网工程任务组IETF的rfc1035国际标准。

DNS查询协议由查询头和请求部分组成。

查询头

DNS查询头结构如上所示,实例中,我们需要设置的唯一字段是消息ID(16位值),它将被复制回服务器响应中。RD(设置为1),告诉DNS服务器在需要时递归查询;QDCOUNT(设置为1),表示我们只有一个域可供查找。

请求部分

请求部分,需要设置的字段有:要查询的域名通过QNAME中设置。不必直接放置域名,可以通过”标签”将其拆分为几个部分。实例中,我们的标签将是”www”,然后是”ijz”,然后是”me”。 QNAME要求在每个标签之前加上前缀长度,并且最后以0结尾。所以我们的QNAME将是:

3,w,w,w,3,i,j,z,2,m,e,0

注意,QNAME必须以0结尾。

QTYPE和QCLASS都将设置为1。

服务器响应

在查询后,服务器响应中,解析的IP地址将位于RDATA的最后4个字节中。为了简单处理,我们只需要获取该部分内容即可。

下面是C整个代码源码:

#include <stdio.h>

#include <stdint.h>

#include <arpa/inet.h>

#include <unistd.h>

int main(void)

{

int i;

uint8_t rsp[512];

uint8_t qry[] = {

0xde,0xad, //ID

0x01,0x00, //RD set

0x00,0x01, //QDCOUNT = 1

0x00,0x00, //ANCOUNT = 0

0x00,0x00, //NSCOUNT = 0

0x00,0x00, //ARCOUNT = 0

3,

w,w,w,

3,

i,j,z,

2,

m,e,

0,

0x00,0x01, //QTYPE

0x00,0x01, //QCLASS

};

struct sockaddr_in sv;

socklen_t len;

int s = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);

sv.sin_family = AF_INET;

sv.sin_port = htons(53);

sv.sin_addr.s_addr = inet_addr(“114.114.114.114”);

sendto(s,qry,sizeof(qry),0,(struct sockaddr*)&sv,sizeof(sv));

i = recvfrom(s,rsp,512,0,(struct sockaddr*)&sv,&len);

printf(“请求的域名IP地址为: %d.%d.%d.%d\n”,rsp[i-4],rsp[i-3],rsp[i-2],rsp[i-1]);

close(s);

return 0;

}

编译及查询:

© 版权声明
THE END
喜欢就支持一下吧
点赞12 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片