DNS协议解析
来源:互联网 发布:绿榴莲网络班价格 编辑:程序博客网 时间:2024/06/05 17:43
DNS协议解析
项目需要,所以要多DNS协议的报文进行解析。读了《TCP/IP详解 卷1》的关于DNS部分的内容后,开始写代码做解析。
参考资料:
http://blog.163.com/libo_5/blog/static/1569685201031433013508/
http://libo.deng.blog.163.com/blog/static/401574222007850244930/
代码:
void GetDNSHost(unsigned char * pDataChar, int begin, char *host){ unsigned char *p = pDataChar+begin; int len = *p; while(len) { if ((*p & 0xC0) == 0xC0) // 如果是一个压缩指针 { len = ntohs(*(unsigned short *) p); len = len & 0x03FFF; GetDNSHost(pDataChar, len, host); break; } else { len = *p; strncpy(host, (char*)p+1, len); strcpy(host+len, "."); // 将数字替换为点。 这样简单处理的后果是域名最后会有一个点。 p = p + len +1 ; host = host + len + 1; } len = *p; }}
主代码,不是完整代码,只是项目代码一部分的简化版本
// dns if( (sport == 53 || dport == 53) && (pTransPacket->nPacketType == IPPROTO_UDP) ) { if (pTransPacket->nDataLen <= 12) return 0; // 分析报文头部 unsigned char *pDataChar = pTransPacket->pDataChar; // 报文数据 DNSPacket *dnsPacket = (DNSPacket * )(pDataChar); unsigned short id = ntohs(dnsPacket->id); unsigned short sign = ntohs(dnsPacket->sign); unsigned short qdCount = ntohs(dnsPacket->qdCount); // 问题数 unsigned short anCount = ntohs(dnsPacket->anCount); // 回答数 unsigned short nsCount = ntohs(dnsPacket->nsCount); // 授权资源记录数 unsigned short arCount = ntohs(dnsPacket->arCount); // 额外资源记录数 int curLen = 12; // 当前分析位置, 头部分析完成,共12字节 if ((sign & 0x8000) == 0) // 查询报文 { // 分析第一个问题,一般都只有一个问题 char hostname[256]; GetDNSHost(pDataChar, curLen, hostname); // debug info { printf("DNS REQUEST:\n"); printf("id: %4X\nsign:%4X\n问题数:%u\n回答数:%u\n授权资源记录数:%u\n额外资源记录书:%u\n", id, sign, qdCount, anCount, nsCount, anCount); printf("询问host: %s\n\n", hostname); } } else // 响应报文 {/* // 调试使用,将所有响应报文打印出来 { printf("响应报文内容:\n"); for(int i = 0;i<pTransPacket->nDataLen;i++) { if(i%4==0 && i!=0) printf("\n"); printf("%02X ",pTransPacket->pDataChar[i]); } printf("\n"); }*/ // debug info { printf("DNS RESPONSE:\n"); printf("id: %4X\nsign:%4X\n问题数:%u\n回答数:%u\n授权资源记录数:%u\n额外资源记录书:%u\n", id, sign, qdCount, anCount, nsCount, anCount); } // 响应报文的查询问题 { // 查询问题字段格式: 查询名 + 查询类型(2字节)+ 查询类(2字节) char hostname[256]; GetDNSHost(pDataChar, curLen, hostname); printf("响应问题: %s\n", hostname); curLen += strlen(hostname) + 1 + 4; // 响应报文的查新问题字段一般不会又压缩的,内容长度为 host长度+1 +查询类型(2字节)+查询类(2字节) } // 响应报文的回答格式 // 域名(不定字节) + 查询类型(2字节)+ 查询类(2字节)+ 生存时间(4字节)+ 资源数据长度(2字节)+ 资源数据(长度由前一个字段确定) // 其中域名一般为压缩方式,指向上一个问题或者回答的域名,一般2个字节 { for (int i = 0; i < anCount; i++) // 分析每一个回答 { // 域名 char hostname[256]; GetDNSHost(pDataChar, curLen, hostname); printf("回答%d: %s----", i, hostname); uint16_t dns_type = ntohs(*(unsigned short *) (pDataChar + curLen + 2)); uint16_t dns_class = ntohs(*(unsigned short *) (pDataChar + curLen + 2 + 2)); uint16_t dns_len = ntohs(*(unsigned short *) (pDataChar + curLen + 2 + 2 + 2 + 4)); if (dns_type == 1) // 查询类型为A, 是一个4个字节的ip地址 { struct in_addr addr; addr.s_addr = *(unsigned int *) (pDataChar + curLen + 2 + 2 + 2 + 4 + 2); char *ip = inet_ntoa(addr); curLen += 2 + 2 + 2 + 4 + 2 + 4; printf("A----ip:%s\n", ip); } else if (dns_type == 5) // 查询类型为 CNAME, 一个域名 { char hostname[256]; GetDNSHost(pDataChar, curLen + 2 + 2 + 2 + 4 + 2, hostname); printf("CNAME----host: %s\n", hostname); curLen += 12 + dns_len; } } printf("\n"); } } }
0 0
- DNS协议解析
- DNS协议解析
- DNS协议解析
- DNS协议解析1--DNS请求协议
- 【mDNS】本地DNS解析协议
- nDPI的DNS协议解析
- DNS 域名解析 (主机解析 地址解析 ) 网络协议
- DNS协议
- DNS协议
- DNS协议
- DNS 协议
- DNS协议
- DNS协议
- DNS协议
- DNS协议
- DNS协议
- DNS协议
- DNS协议
- SQL 数据类型:MySQL 数据类型
- Netty 权威指南之Google protobuf 编解码
- 看大型的支付系统如支付宝等如何实现风控的!
- 关于按键扫描程序
- [VIM]Linux下打造自己的IDE
- DNS协议解析
- 推荐大家几款软件
- 第八章 作业
- switch命令行
- 删除dbms_job
- android学习笔记五—android的存储2 文件的读取与写入
- RFS之webdriver
- leetcode-2Add Two Numbers
- Scrum 扫盲篇