DNS 报文详解
目录
本文主要讲解 DNS 的报文结构
DNS 简介
DNS(域名系统)负责将我们熟知的域名翻译成 IP 地址,其相关定义由 RFC 1034 和 RFC 1035 给出。
为了实现更好的扩展性,DNS 采用分层次的服务器组织结构,主要分为三层:
- 根 DNS 服务器
- 顶级域名(TLD)DNS 服务器
- 权威 DNS 服务器
这些服务器的层次结构如下图所示:
关于 DNS 的工作过程及相关信息,请参见深入浅出 DNS 解析,本文主要介绍 DNS 报文结构。
DNS 报文结构
DNS 报文包含以下几个部分:
-
首部(前 12 个字节):
- 标识符(2 字节):用于标识请求及其响应报文
- 标志(2 字节):
- QR(1 bit):查询/响应标志,
0
表示查询,1
表示响应 - opcode(4 bit):操作码
0
:标准查询1
:反向查询2
:服务器状态请求[3,15]
:保留值
- AA(1 bit):授权回答标志,表示响应服务器是否为域名的权威服务器
- TC(1 bit):截断标志,表示报文是否因超过长度而被截断
- RD(1 bit):期望递归标志,由请求方设置,响应方返回相同值
- RA(1 bit):支持递归标志,由响应方设置,表示是否支持递归查询
- rcode(4 bit):返回码
0
:无错误1
:格式错误2
:服务器失败3
:域名不存在4
:查询类型不支持5
:查询被拒绝[6,15]
:保留值
- QR(1 bit):查询/响应标志,
-
数量字段(8 字节):
- Questions:查询问题数量
- Answers:回答数量
- Authoritative nameservers:授权域名服务器数量
- Additional records:附加信息数量
-
问题(Questions)部分包括:
- 查询的域名 8bit 为单位,长度不受限
- 查询的协议类型 16bit
- 查询的类 16bit
-
回答(Answers)/权威(Authoritys)/附加(Additionals)部分格式相同:
- NAME 资源记录包含的域名.
- TYPE 表示 DNS 协议的类型.
- CLASS 表示 RDATA 的类.
- TTL 4 字节无符号整数表示资源记录可以缓存的时间。0 代表只能被传输,但是不能被缓存。
- RDLENGTH 2 个字节无符号整数表示 RDATA 的长度
- RDATA 不定长字符串来表示记录,格式根 TYPE 和 CLASS 有关。比如,TYPE 是 A,CLASS 是 IN,那么 RDATA 就是一个 4 个字节的 ARPA 网络地址。
RRs 说明
每个 DNS 响应报文包含一条或者多条资源记录(resource records ,RRs),资源记录包含下列字段的 4 元组:
(Name,Value,Type,TTL)
其中 TTL 表示生存时间,决定了资源记录应该从缓存中删除的时间。
- 如果是 Type=A,Name 为主机名,Value 是对应的 IP 地址(如 bar.foo.com,xxx.xxx.xxx.xxx,A)
- 如果是 Type=NS,Name 为一个域(如 foo.com),Value 是知道如何获取该域中的主机 IP 地址的权威 DNS 服务器的主机名(如 foo.com,dns.foo.com,NS)
- 如果是 Type=CNAME,Value 是别名为 Name 的主机对应的规范主机名。(如 foo.com,relay1.bar.foo.com,CNAME)
- 如果是 Type=MX,Value 是别名为 Name 的邮件服务器对应的规范主机名。(如 foo.com,mail.bar.foo.com,MX)
实例
这里我们使用 WireShark 抓包实际看看,启动 WireShark 时可以设置捕获过滤器为:
udp port 53
这样我们只抓取通过 UDP 53 端口的 DNS 请求,此外如果需要仅仅显示特定的 DNS 查询,还可以进一步应用显示过滤器,例如这里我们仅查看www.techkoala.top
的查询记录,则显示过滤器设置为:
dns.qry.name==www.techkoala.top
可以看出
- 标识为:0x0000cd13
- 这是一个请求报文,仅在 Questions 部分有值
同时 WireShark 还贴心的告诉我们,响应报文的在总抓取包的编号为 10,方便我们快速找到请求报文对应的响应报文。
参考
- [1] Computer Networking A Top-Down Approach
- [2] DNS 请求报文详解