DNS协议初探
本文正在参与 “网络协议必知必会”征文活动
DNS 使用TCP还是UDP协议?
DNS 迭代查询 和 递归查询 是什么?
如何构建DNS报文?
- 什么是DNS
DNS: (Domain Name System) 域名系统, 用户在使用常用网络软件,例如: 浏览器,邮件 等,但是这些服务需要指定服务器的ip地址和端口号,这个难以记忆,大家更喜欢易读、有一定含义的名字,DNS就能满足这个要求,实现将域名映射为IP地址,这个就称为域名解析。目前互联网 DNS为分布式数据库, 域名服务器分布在世界各地,每个服务器也只存储了部分域名信息。
1.1 域名层次化
域名结构由标号序列组成,标点符号用点隔开, 例如: juejin.cn.
www.jd.com.
可总结为: ....三级域名.二级域名.顶级域名.根域名(可省略)
根
截止目前为止,全球上共有13个根服务器 ,从 a - m
1 | bash复制代码# yum -y install bind-utils |
顶级域名分类:
- 国家顶级域名nTLD
- cn: 表示中国
- us: 表示美国
- jp: 表示日本
- …
- 通用顶级域名gTLD
- com: 表示工商企业
- net: 表示网络提供商
- gov: 政府专用
- …
- 基础结构域名
- arpa
1.2 域名服务器分类
域名服务器以区为单位,可以分为: 1. 根域名服务器 2. 顶级域名服务器 3. 权威域名服务器 4. 中间域名服务器
根域名服务器
全球共有13个根域名服务器,可通过 dig
获取。
顶级域名服务器
TLD服务器,负责管理该顶级域名下的二级域名。
权威域名服务器
负载一个区的域名服务器,保存该区的域名 和 IP地址映射关系。
中间服务器
不属于如上三种服务器,就是中间域名服务器。
1.3 通过实例来判断服务器分类
本次查询,DNS服务器信息如下
- 本地域名服务器: 61.139.2.69
- 根域名服务器: a.root-servers.net (198.41.0.4#53)
- 顶级域名服务器: g.dns.cn (66.198.183.65#53)
- 权威域名服务器: vip4.alidns.com (47.113.183.36#53)
利用dig追踪日志如下
dig +trace 可以追踪请求
1 | bash复制代码# dig +trace juejin.cn. @61.139.2.69 |
解析请求图大致如下
1.4 DNS递归解析和迭代解析
递归查询: 在进行查询时,若没有被查询的域名信息,则进行代理查询,直至查询到IP地址/或者是查询失败 , 然后返回给本地域名服务器。
迭代查询: 不会进行代理查询请求,而是将结果或者是下一跳域名服务器返回给本地域名服务器。
图示
迭代查询
递归查询
- DNS报文解析
参考 rfc1035 datatracker.ietf.org/doc/html/rf…
请求报文
响应报文
2.1 DNS 整个报文格式
1 | bash复制代码 +---------------------+ |
2.2 Head: 请求头
1 | bash复制代码 1 1 1 1 1 1 |
ID: 16bit 查询/响应编号
作为 查询 和 应答标识ID
QR: 1bit 报文类型
0: 查询
1: 响应
Opcode: 4bit 查询的类型
0: 标准查询
1: 反查询
2: 服务器状态请求
3-15: 暂时闲置
AA: 1bit 权威应答
1: 是
0: 否
TC: 1bit 超出最大允许的长度(UDP包为512字节)
UDP 包为 512 字节,若返回报文超过512个字节,则需要将状态标志位 TC 置为1 然后将报文返回给客户端,客户端收到后会再次使用 TCP 进行查询请求
1: 超出最大长度,截断
0: 正常
RD: 1bit 期望递归查询
1: 需要递归查询
0: 不需要递归查询
RA: 1bit 可用递归 , 用于响应报文中
1: 支持递归
0: 不支持递归
Z: 3bit
保留
RCODE: 4bit 响应代码
0: 没有错误
1: 格式错误
2: 服务器故障
3: 名称错误
4: 不支持请求类型的查询
5: 服务器拒绝查询
6-15: 备用
2.3 Question 查询请求
1 | bash复制代码 1 1 1 1 1 1 |
QNAME: 表示查询的域名
每个标签由一个8字节的长度 和 响应的字符组成
例如 juejin.com
在报文中QNAME应该展示为
6 j u e j in
3 c o m
0
QTYPE: 16bit 请求的类型
1: A
2: NS
3: MD
4: MF
5: CNAME
6: SOA
7: MB
8: MG
9: MR
10: NULL
11: WKS
12: PTR
13: HINFO
14: MINFO
15: MX
16: TXT
QCLASS: 16bit 请求的方式
1: 一般网络请求
2: CSNET
3: CHAOS
4: Hesiod
2.4 Answer 响应报文
1 | bash复制代码 1 1 1 1 1 1 |
**NAEM: 16bit **
资源记录域名 , 采用 2个byte 来表示 , CO 为固定标记位,代表后面的值为偏移量
1 | bash复制代码 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ |
TYPE 16bit
RDATA资源类型
CLASS: 16bit
请求类型
TTL: 32bit
缓存时间,为0则不能缓存
RDLENGTH: 16bit
RDATA字节数
RDATA: RDLENGTH byte
资源记录值
- DNS golang 代码案例
3.1 获取请求报文
获取/生成A记录报文Demo 代码放在了 gitee 上 gitee.com/pdudo/Sampl…
代码
1 | golang复制代码package main |
启动服务器 并且 使用nslookup模拟请求
1 | bash复制代码# go build |
客户端
1 | bash复制代码# nslookup juejin.com 127.0.0.1 |
程序输出
1 | bash复制代码# ./testDNSQuery |
生成响应报文
修改代码
1 | golang复制代码package main |
利用nslookup查看效果
1 | bash复制代码# nslookup juejin.com 127.0.0.1 |
1 | bash复制代码var code = "df7cfb57-4300-4caa-a3bc-3a489833b53c" |
完
本文转载自: 掘金