DNS请求流程和报文解析

2023-11-05

DNS

域名系统(英文: Domain Name System, 缩写: DNS)是互联网的一项服务,它作为将域名和 IP 地址相互映射的一个分布式数据库,能够使人更方便地访问互联网。DNS)的作用是将人类可读的域名(如,www.example.com) 转换为机器可读的 IP 地址 (如,192.0.2.44)。

域名结构

internet在命名时采用了层次结构的命名方法。每个域名都是一个标号序列(labels),用字母,数字,连接符组成。它用点号分割成一个个标号,每个标号可以看成是一个个的层级,级别低的写在左边,级别高的写在右边,域名服务主要基于UDP实现。

顶级域  ----    com   edu     gov     net
第二级域----    baidu    163
第三级域----    www     gitlab

域名解析过程

在有了域名结构之后需要有机器对其进行解析,而不同层级的根据高低级别由根域名服务器,顶级域名服务器,权限域名服务器,本地域名服务器。域名解析过程分为两大步骤:第一个步骤是本机向本地域名服务器发出一个DNS请求报文,报文携带要查询的域名,第二个步骤是本地域名服务器向本机回应一个DNS响应报文,包含域名对应的IP地址。
以百度为例具体流程描述如下:

  1. 主机 192.168.11.123 先向本地域名服务器 192.168.1.2 进行递归查询
  2. 本地域名服务器采用迭代查询,向一个根域名服务器进行查询
  3. 根域名服务器告诉本地域名服务器,下一次应该查询的顶级域名服务器 baidu.com 的IP 地址
  4. 本地域名服务器向顶级域名服务器 baidu.com 进行查询
  5. 顶级域名服务器 .com 告诉本地域名服务器,下一步查询权限服务器 www.baidu.com的 IP 地址
  6. 本地域名服务器向权限服务器 www.baidu.com 进行查询
  7. 权限服务器 www.baidu.com 告诉本地域名服务器所查询的主机的 IP 地址
  8. 本地域名服务器最后把查询结果告诉 122.152.222.180

递归查询:本机向本地域名服务器发出一次查询请求,就静待最终的结果。如果本地域名服务器无法解析,自己会以 DNS 客户机的身份向其它域名服务器查询,直到得到最
终的 IP 地址告诉本机

迭代查询:本地域名服务器向根域名服务器查询,根域名服务器告诉它下一步到哪里去查询,然后它再去查,每次它都是以客户机的身份去各个服务器查询

协议报文格式

请添加图片描述
报文分为头部和正文:

头部

会话标识(2 字节):是 DNS 报文的 ID 标识,请求和应答是相同的。

标志(2字节):
请添加图片描述

QR(1bit)查询/响应标志,0 为查询,1 为响应
opcode(4bit)0 表示标准查询,1 表示反向查询,2 表示服务器状态请求
AA(1bit)表示授权回答
TC(1bit)表示可截断的
RD(1bit)表示期望递归
RA(1bit)表示可用递归
rcode(4bit)表示返回码,0 表示没有差错,3 表示名字差错,2 表示服务器错误(Server Failure)
数量字段(总共 8 字节):Questions、Answer RRs、Authority RRs、Additional RRs 各自表示后面的四个区域的数目。

正文

Queries
请添加图片描述

查询名:长度不固定,不填充字节,一般表示反向查询,即由IP地址反查域名格式如下

5baidu3com0
5表示后面域名的长度,3同理,最后必须为0

查询类型:
请添加图片描述

查询类:通常为1,表明internet数据
原纪录(RR):包括回答区域,授权区域和附加区域
请添加图片描述

c实现DNS请求


#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>

#define DNS_SERVER_PORT		53
#define DNS_SERVER_IP		"114.114.114.114"

#define DNS_HOST			0x01
#define DNS_CNAME			0x05

struct dns_header{

	unsigned short id;
	unsigned short flags;

	unsigned short questions;
	unsigned short answer;

	unsigned short authority;
	unsigned short additional;
	
};

struct dns_question{

	int length;
	unsigned short qtype;
	unsigned short qclass;
	unsigned char *name;

};

struct dns_item{

	char *domain;
	char *ip;

};

//client send to dns server

int dns_create_header(struct dns_header *header){

	if(header == NULL) return -1;
	memset(header,0,sizeof(struct dns_header));

	//random
	srandom(time(NULL));
	header->id = random();

	header->flags = htons(0x0100);;
	header->questions = htons(1);

	return 0;
	
}

//hostname: www.baidu.com
//www
//baidu
//com

//name: 3www5baidu3com0

int dns_creat_questions(struct dns_question *question, const char *hostname){

	if(question == NULL || hostname==NULL) return -1;
	memset(question,0,sizeof(struct dns_question));

	question->name =(char *)malloc(strlen(hostname) + 2);
	if(question->name == NULL){
		return -2;
	}
	
	question->length = strlen(hostname) + 2;

	question->qtype = htons(1);
	question->qclass = htons(1);

	//name
	const char delim[2] = ".";
	char *qname = question->name;
	
	char *hostname_dup = strdup(hostname);	//strdup --> malloc
	char *token = strtok(hostname_dup,delim);	//www.0voice.com

	while(token != NULL){

		size_t len = strlen(token);

		*qname = len;
		qname++;

		strncpy(qname, token, len+1);
		qname += len;

		token = strtok(NULL, delim);
	}

	free(hostname_dup);
	
}

//

int dns_build_request(struct dns_header *header, struct dns_question *question, char *request, int rlen){

	if(header == NULL || question == NULL || request == NULL) return -1;
	memset(request, 0, rlen);

	//header --> server	
	memcpy(request,header, sizeof(struct dns_header));
	int offset = sizeof(struct dns_header);
		
	//question -->request
	memcpy(request+offset, question->name, question->length);
	offset += question->length;

	memcpy(request+offset, &question->qtype,sizeof(question->qtype));
	offset += sizeof(question->qtype);

	memcpy(request+offset, &question->qclass,sizeof(question->qclass));
	offset += sizeof(question->qclass);
	
	return offset;

}

static int is_pointer(int in) {
	return ((in & 0xC0) == 0xC0);
}

static void dns_parse_name(unsigned char *chunk, unsigned char *ptr,char *out,int *len){

	int flag = 0, n = 0, alen = 0;
	char *pos = out + (*len);

	while (1) {

		flag = (int)ptr[0];
		if (flag == 0) break;

		if (is_pointer(flag)) {
			
			n = (int)ptr[1];
			ptr = chunk + n;
			dns_parse_name(chunk, ptr, out, len);
			break;
			
		} else {

			ptr ++;
			memcpy(pos, ptr, flag);
			pos += flag;
			ptr += flag;

			*len += flag;
			if ((int)ptr[0] != 0) {
				memcpy(pos, ".", 1);
				pos += 1;
				(*len) += 1;
			}
		}
	
	}


}
static int dns_parse_response(char *buffer, struct dns_item **domains){

	int i = 0;
	unsigned char *ptr = buffer;

	ptr += 4;
	int querys = ntohs(*(unsigned short*)ptr);

	ptr += 2;
	int answers = ntohs(*(unsigned short*)ptr);

	ptr += 6;
	for(i = 0;i< querys; i ++){
	while(i){
		int flag = (int)ptr[0];
		ptr += (flag + 1);

		if(flag = 0) break;

	}
	ptr += 4;	

	}

	char cname[128], aname[128], ip[20], netip[4];
	int len, type, ttl, datalen;

	int cnt = 0;
	struct dns_item *list = (struct dns_item*)calloc(answers, sizeof(struct dns_item));
	if(list == NULL){
		return -1;
	}

	for(i = 0; i<answers; i++){

		bzero(aname, sizeof(aname));
		len = 0;

		dns_parse_name(buffer, ptr, aname, &len);
		ptr += 2;

		type = htons(*(unsigned short*)ptr);
		ptr += 4;

		ttl = htons(*(unsigned short*)ptr);
		ptr += 4;

		datalen = ntohs(*(unsigned short*)ptr);
		ptr += 2;

		if (type == DNS_CNAME) {

			bzero(cname, sizeof(cname));
			len = 0;
			dns_parse_name(buffer, ptr, cname, &len);
			ptr += datalen;
			
		} else if (type == DNS_HOST) {

			bzero(ip, sizeof(ip));

			if (datalen == 4) {
				memcpy(netip, ptr, datalen);
				inet_ntop(AF_INET , netip , ip , sizeof(struct sockaddr));

				printf("%s has address %s\n" , aname, ip);
				printf("\tTime to live: %d minutes , %d seconds\n", ttl / 60, ttl % 60);

				list[cnt].domain = (char *)calloc(strlen(aname) + 1, 1);
				memcpy(list[cnt].domain, aname, strlen(aname));
				
				list[cnt].ip = (char *)calloc(strlen(ip) + 1, 1);
				memcpy(list[cnt].ip, ip, strlen(ip));
				
				cnt ++;
			}
			
			ptr += datalen;
		}
	}

	*domains = list;
	ptr += 2;

	return cnt;
	

}


int dns_client_commit(const char *domain){

	int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
	if(sockfd < 0){
		return -1;
	}

	struct sockaddr_in servaddr = {0};
	servaddr.sin_family = AF_INET;
	servaddr.sin_port = htons(DNS_SERVER_PORT);
	servaddr.sin_addr.s_addr = inet_addr(DNS_SERVER_IP);

	int ret = connect(sockfd,(struct sockaddr*)&servaddr,sizeof(servaddr));
	printf("connect: %d\n", ret);
	
	struct dns_header header = {0};
	dns_create_header(&header);

	struct dns_question question = {0};	
	dns_creat_questions(&question, domain);

	char request[1024] = {0};
	int length = dns_build_request(&header, &question, request, 1024);

	//requst
	int slen = sendto(sockfd, request, length, 0, (struct sockaddr*)&servaddr, sizeof(struct sockaddr));
	printf("requst: %d\n", slen);
	//recvfrom
	char response[1024] = {0};
	struct sockaddr_in addr;
	size_t addr_len = sizeof(struct sockaddr_in);

	int n = recvfrom(sockfd, response, sizeof(response), 0, (struct sockaddr*)&addr, (socklen_t*)&addr_len);
	printf("recvfrom: %d\n", n);

	struct dns_item *dns_domain = NULL;
	dns_parse_response(response,&dns_domain);
	free(dns_domain);

	return n;

}

int main(int argc,char *argv[]){

	if(argc < 2) return -1;

	dns_client_commit(argv[1]);

}


_in);

	int n = recvfrom(sockfd, response, sizeof(response), 0, (struct sockaddr*)&addr, (socklen_t*)&addr_len);
	printf("recvfrom: %d\n", n);

	struct dns_item *dns_domain = NULL;
	dns_parse_response(response,&dns_domain);
	free(dns_domain);

	return n;

}

int main(int argc,char *argv[]){

	if(argc < 2) return -1;

	dns_client_commit(argv[1]);

}


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

DNS请求流程和报文解析 的相关文章

  • pandas用法整理

    处理表格数据的时候经常用到pandas 每次用的时候都要去查函数 每次记不住 每次都查 哈哈哈 自己整理一下 码住 一 Pandas的数据类型 进行数据分析时 如何正确使用数据类型 这非常重要 在pandas中的数据类型和python原生数
  • 服务器超线程的好处

    服务器超线程的好处 1 提高性能 超线程通过提高整体系统吞吐量显着提高服务器性能 通过允许多个线程在单个物理内核上同时执行 超线程减少了空闲时间并最大限度地利用了可用资源 这会加快任务执行速度并缩短应用程序的响应时间 尤其是在多线程工作负载
  • 成为一个黑客,就按照这个路线来!

    前几天一个同学在聊天中提到毕业后想要从事网络安全方向的工作 虽然他本身也是学计算机的 但是又怕心有余而力不足 因为 从事网络安全方面的工作向来起点都比较高 大学里少有开设这类课程的 在学校能够学到的知识比较有限 网上的关于这方面课程的质量又
  • nohup - 后台执行

    nohup no hang up 语法 nohup Command Arg 使用示例 nohup python a py 日志将被保留在 当前文件夹下的 nohup out 将日志放到文件 不输出到终端 echo hello gt 1 tx
  • 这些专利知识你知道吗?

    专利作为一种重要的知识产权保护形式 专利不仅成为了企业核心竞争力的重要组成部分 也成为了国家创新发展的重要支撑 专利是指国家专利主管机关授予发明创造申请人的一种专有权 这种专有权具有独占性 排他性和法律强制性 能够为持有者带来经济利益和竞争
  • 自定义编写zabbix_agent脚本

    vi usr lib systemd system zabbix agent servicce Unit Description Zabbix Agent After syslog target After network target S
  • Web 安全漏洞之 OS 命令注入

    什么是 OS 命令注入 上周我们分享了一篇 Web 安全漏洞之 SQL 注入 其原理简单来说就是因为 SQL 是一种结构化字符串语言 攻击者利用可以随意构造语句的漏洞构造了开发者意料之外的语句 而今天要讲的 OS 命令注入其实原理和 SQL
  • 线程安全(中)--彻底搞懂synchronized(从偏向锁到重量级锁)

    接触过线程安全的同学想必都使用过synchronized这个关键字 在java同步代码快中 synchronized的使用方式无非有两个 通过对一个对象进行加锁来实现同步 如下面代码 synchronized lockObject 代码 对
  • 前端必备的 web 安全知识手记

    前言 安全这种东西就是不发生则已 一发生则惊人 作为前端 平时对这方面的知识没啥研究 最近了解了下 特此沉淀 文章内容包括以下几个典型的 web 安全知识点 XSS CSRF 点击劫持 SQL 注入和上传问题等 下文以小王代指攻击者 话不多
  • WEB前端常见受攻击方式及解决办法总结

    一个网址建立后 如果不注意安全问题 就很容易被人攻击 下面讨论一下集中漏洞情况和放置攻击的方法 一 SQL注入 所谓的SQL注入 就是通过把SQL命令插入到web表单提交或输入域名或页面请求的查询字符串 最终达到欺骗服务器执行恶意的SQL命
  • 用户数据中的幸存者偏差

    幸存者偏差 Survivorship bias 是一种常见的逻辑谬误 意思是没有考虑到筛选的过程 忽略了被筛选掉的关键信息 只看到经过筛选后而产生的结果 先讲个故事 二战时 无奈德国空防强大 盟军战机损毁严重 于是军方便找来科学家统计飞机受
  • 白帽子如何快速挖到人生的第一个漏洞 | 购物站点挖掘商城漏洞

    本文针对人群 很多朋友们接触安全都是通过书籍 网上流传的PDF 亦或是通过论坛里的文章 但可能经过了这样一段时间的学习 了解了一些常见漏洞的原理之后 对于漏洞挖掘还不是很清楚 甚至不明白如何下手 可能你通过 sql labs 初步掌握了sq
  • 2024年金三银四网络安全考试试题

    2023年金三银四网络安全考试试题 1 关于数据使用说法错误的是 A 在知识分享 案例中如涉及客户网络数据 应取敏感化 不得直接使用 B 在公开场合 公共媒体等谈论 传播或发布客户网络中的数据 需获得客户书面授权或取敏感化 公开渠道获得的除
  • 通俗易懂,十分钟读懂DES,详解DES加密算法原理,DES攻击手段以及3DES原理

    文章目录 1 什么是DES 2 DES的基本概念 3 DES的加密流程 4 DES算法步骤详解 4 1 初始置换 Initial Permutation IP置换 4 2 加密轮次 4 3 F轮函数 4 3 1 拓展R到48位 4 3 2
  • 远程控制软件安全吗?一文看懂ToDesk、RayLink、TeamViewer、Splashtop相关安全机制_raylink todesk

    目录 一 前言 二 远程控制中的安全威胁 三 国内外远控软件安全机制 ToDesk RayLink Teamviewer Splashtop 四 安全远控预防 一 前言 近期 远程控制话题再一次引起关注 据相关新闻报道 不少不法分子利用远程
  • 网络安全(黑客)自学

    1 网络安全是什么 网络安全可以基于攻击和防御视角来分类 我们经常听到的 红队 渗透测试 等就是研究攻击技术 而 蓝队 安全运营 安全运维 则研究防御技术 2 网络安全市场 一 是市场需求量高 二 则是发展相对成熟入门比较容易 3 所需要的
  • 短信系统搭建主要因素|网页短信平台开发源码

    短信系统搭建主要因素 网页短信平台开发源码 随着移动互联网的快速发展 短信系统已成为企业和个人进行信息传递的重要工具 建立一个高效可靠的短信系统对于企业来说非常重要 下面我们将介绍一些影响短信系统搭建的主要因素 1 平台选择 在搭建短信系统
  • 【无标题】

    大家都知道该赛项的规程和样题向来都是模棱两可 从来不说具体的内容 导致选手在备赛时没有头绪 不知道该怎么训练 到了赛时发现题目和备赛的时候完全不一样 那么本文将以往年信息安全管理与评估赛项经验来解读今年2023年国赛的规程 帮助选手们指明方
  • 网工内推 | 上市公司同程、科达,五险一金,年终奖,最高12k*15薪

    01 同程旅行 招聘岗位 网络工程师 职责描述 1 负责职场 门店网络规划 建设 维护 2 负责网络安全及访问控制 上网行为管理和VPN设备的日常运维 3 负责内部相关网络自动化和系统化建设 4 优化与提升网络运行质量 制定应急预案 人员培
  • 【安全】网络安全态势感知

    文章目录 一 态势感知简介 1 概念 2 形象举例 3 应具备的能力 二 为什么要态势感知 为什么网络安全态势感知很重要 三 态势感知系统的功能 四 如何评估态势感知的建设结果 五 什么是态势感知的三个层级 四 业界的态势感知产品 1 安全

随机推荐

  • idea只读模式(注释变为*)

    强迫症患者 习惯了idea的 注解 突然不小心点了idea的 注解 想要变回来的解决方式 idea注释突然变成不可编辑模式 此时可以调整Reader Mode 把Enable Reader mode取消即可 以上就是我对idea变为只读模式
  • Orange‘s:一个操作系统的实现学习笔记1

    安装虚拟机 bochs NASM 前言 一 安装虚拟机VMware和操作系统 安装Ubuntu 安装VMTools 1 提示直接安装 2 点击选项安装 安装后记 二 安装bochs和NASM 1 安装bochs 2 安装NASM 安装后记
  • Perl 函数参考

    Perl wait 函数 wait该函数等待子进程终止 返回已故进程的进程ID 进程的退出状态包含在 中 句法 以下是此函数的简单语法 wait 返回值 如果没有子进程 则此函数返回 1 否则将显示已故进程的进程ID Perl waitpi
  • JVM的运行时内存区域划分详细讲解

    文章目录 一 运行时数据区域 1 程序计数器 Program Counter Register 2 Java 虚拟机栈 Java Virtual Machine Stacks 3 本地方法栈 Native Method Stack 4 Ja
  • 【VirtualBox系列】VirtualBox设置虚拟机网络绝对详细

    前言知识 在学习配置网络之前 我们需要先了解下关于virtualBox的三种网络模式 搞懂虚拟机VirtualBox网络配置 需求分析 现在如何实现一种效果 我想达到主机可以访问虚拟机 并且虚拟机能够访问外网 还有如果我更换了路由器 之前配
  • Excel基础操作

    目录 第一节 新建Excel工作簿 第二节 认识Excel操作界面 第三节 上下文选项卡和自定义功能区 第四节 文件选项卡的设置 第五节 输入和编辑数据 第六节 数据的显示 第七节 数据输入技巧 第八节 填充与序列 第九节 填充选项 第十节
  • LVGL学习 stm32f407-board-lvgl v8.3移植

    LVGL学习 stm32f407 board lvglv8 3移植 移植过程有问题 请参考正点原子的教程或者视频 硬件平台 STM32F407ZGT6核心板 3 2寸屏幕 LVGL LVGL Light and Versatile Grap
  • CloudCompare 二次开发(3)——计算点云质心

    目录 一 概述 二 代码集成 三 结果展示 一 概述 不依赖任何第三方点云相关库 使用ClopudCompare计算点云质心 本文由CSDN点云侠原创 原文链接 爬虫网站自重 二 代码集成 1 mainwindow h文件public中添加
  • Python数据分析是什么?为什么要对比Excel学习

    Python本身是一门编程语言 应用于Web开发 爬虫 机器学习等多个领域 但是除了这些 今天小千要告诉你Python大热的一个学习方向 那就是Python数据分析 我常常会听到这样的问题 金融分析中 为什么我要学习像Python这样的编程
  • H5跳转微信小程序,通过获取URL Scheme,实现短信跳转小程序,微信跳转小程序,邮件跳转小程序,外部链接跳转小程序

    H5链接跳转小程序有2种方式 第一种 通过微信官方提供的标签wx open launch weapp 打开小程序 第二种 通过获取URL Scheme实现链接跳转小程序 一 wx open launch weapp 官方文档https de
  • java 读取word_java poi word读取

    用 poi 读取word文件 老是报错 org apache poi poifs filesystem NotOLE2FileException Invalid header signature read 0xC9D33C3A6D6F724
  • 期货开户的具体程序是什么?

    一 开户 1 对客户的条件要求 客户应至少具备以下条件 1 具有完全民事行为能力 2 有与进行期货交易相适应的自有资金或者其他财产 能够承担期货交易风险 3 有固定的住所 4 符合国家 行业的有关规定 二 保证金 中小投资者可以等待股指期货
  • tinyMCE编辑器去除换行增加的P标签

    tinyMCE编辑器去除换行增加的P标签 tinyMCE里使用回车后会加P标签 如何变成原本的br标签呢 搜索出force p newlines false参数可以关闭自动添加P标签 但实际测试没什么变化 查询了一下源码发现带 p 的就fo
  • 视差动画 - 雅虎新闻摘要加载

    基础知识 继 Android实现旋转动画的两种方式 我们了解了 Android实现旋转的两种基本方法之后 我们来写一个综合案例 效果展示 代码实现 实现思路 从效果中我们可以看到 可以将其分为三个动画 1 旋转动画 Android实现旋转动
  • linux桌面小程序开发(pyqt+新增csv增删改查功能)附加章节

    温馨提示 默认运行的是GPU 若发现无法执行 请在参数中替换为CUP 在上一版中需要用到sql 但在这一版中我全部改为了csv进行一个文件的匹配 所以不再需要装mysql了 还有创建字段啥的了 我更新了该小程序的功能 增加了csv文件的增删
  • Logseq 本地端使用 Github 同步

    2020 11 25 更新 Logseq 的网页端同步 Github 有很多 BUG 难以正常使用 解决办法见另一篇文章 Logseq 利用 Obsidian 多端同步 目录 2020 11 25 更新 一 需求分析 二 基本思路 1 Lo
  • HUAWEI MateBook X Pro升级2T SSD并保留一键恢复功能

    手上一台 MateBook X Pro2020款笔记本 SSD为512G 用了几年 随着时间的推移 硬盘空间慢慢不够用了 系统分区与用户分区在WIN10系统下都显示为红色警告 因此有了升级SSD的想法 上网查了很多资料 大多数都有提到Mat
  • NodeJs - for循环的几种遍历方式

    NodeJs for循环的几种遍历方式 一 for循环的几种遍历方式 1 1 遍历的目标不一样 1 2 空属性的遍历 1 3 异步的调用 二 总结 一 for循环的几种遍历方式 我们先来看下for循环的4种不同遍历方式 const arr
  • flutter 屏幕适配插件 flutter_screenutil 的简单使用

    前言 屏幕适配问题一直是app开发中一个绕不开的话题 毕竟现在各种尺寸的设备越来越多 原本一个优美大气的用户页面可能就会因为屏幕尺寸变化而变得杂乱无章 甚至是布局溢出 导致某些重要的信息无法显示 最终并因此而丢失掉用户 因此 屏幕适配是一项
  • DNS请求流程和报文解析

    DNS 域名系统 英文 Domain Name System 缩写 DNS 是互联网的一项服务 它作为将域名和 IP 地址相互映射的一个分布式数据库 能够使人更方便地访问互联网 DNS 的作用是将人类可读的域名 如 www example