1. DNS 是什么?
DNS (Domain Name System 的缩写)的作用非常简单,就是根据域名查出IP地址。你可以把它想象成一本巨大的电话本。
举例来说,如果你要访问域名math.stackexchange.com
,首先要通过DNS查出它的IP地址是151.101.129.69
。
2. 域名的层级
由于后面我会讲到 DNS 的解析过程,因此需要你对域名的层级有一些了解
- 根域名 :
.root
或者.
,通常是省略的 - 域名,如
.com
,.cn
等 - 次级域名,如
baidu.com
里的baidu
,这个用户是可以注册购买的 - 主机域名,比如
baike.baidu.com
里的baike
,这个用户是可分配的
主机名.次级域名.域名.根域名
baike.baidu.com.root复制代码
3. DNS 解析过程
咱们以访问 www.163.com
这个域名为例,来看一看当你访问 www.163.com 时,会发生哪些事:
- 先查找本地 DNS 缓存(自己的电脑上),有则返回,没有则进入下一步
- 查看本地 hosts 文件有没有相应的映射记录,有则返回,没有则进入下一步
- 向本地 DNS 服务器(一般都是你的网络接入服务器商提供,比如中国电信,中国移动)发送请求进行查询,本地DNS服务器收到请求后,会先查下自己的缓存记录,如果查到了直接返回就结束了,如果没有查到,本地DNS服务器就会向DNS的根域名服务器发起查询请求:请问老大,
www.163.com
的ip是啥? - 根域名服务器收到请求后,看到这是个
.com
的域名,就回信说:这个域名是由.com
老弟管理的,你去问他好了,这是.com
老弟的联系方式(ip1)。 - 本地 DNS 服务器接收到回信后,照着老大哥给的联系方式(ip1),马上给
.com
这个域名服务器发起请求:请问.com
大大,www.163.com
的ip 是啥? -
.com
域名服务器接收到请求后,看到这是163.com
的域名,就回信说:这个域名是.163.com
老弟管理的,你就去问他就行了,这是他的联系方式(ip2) - 本地 DNS 服务器接收到回信后,按照前辈的指引(ip2),又向
.163.com
这个权威域名服务器发起请求:请问163.com
大大,请问www.163.com
的ip是啥? -
163.com
权威域名服务器接收到请求后,确认了是自己管理的域名,马上查了下自己的小本本,把www.163.com
的ip告诉了 本地DNS服务器。 - 本地DNS服务器接收到回信后,非常地开心,这下总算拿到了
www.163.com
的ip了,马上把这个消息告诉了要求查询的客户(就是你的电脑)。由于这个过程比较漫长,本地DNS服务器为了节省时间,也为了尽量不去打扰各位老大哥,就把这个查询结果偷偷地记在了自己的小本本上,方便下次有人来查询时,可以快速回应。
总结起来就是三句话
- 从"根域名服务器"查到"域名服务器"的NS记录和A记录(IP地址)
- 从"域名服务器"查到"次级域名服务器"的NS记录和A记录(IP地址)
- 从"次级域名服务器"查出"主机名"的IP地址
4. DNS的缓存时间
上面的几个步骤里,可以看到有两个地方会缓存 DNS 的查询记录,有了缓存,在一定程度上会提高查询效率,但同时在准确率上会有所损失。
因此我们在配置 DNS 解析的时候,会有一个 TTL 参数(Time To Live),意思就是这个缓存可以存活多长时间,过了这个时间,本地 DNS 就会删除这条记录,删除了缓存后,你再访问,就要重新走一遍上面的流程,获取新的地址。
5. DNS 的记录类型
当我们在阿里云买了一个域名后,可以配置我们主机域名解析规则,也就是 记录。
常见的 DNS 记录类型如下
-
A
:地址记录(Address),返回域名指向的IP地址。 -
NS
:域名服务器记录(Name Server),返回保存下一级域名信息的服务器地址。该记录只能设置为域名,不能设置为IP地址。 -
MX
:邮件记录(Mail eXchange),返回接收电子邮件的服务器地址。 -
CNAME
:规范名称记录(Canonical Name),返回另一个域名,即当前查询的域名是另一个域名的跳转,详见下文。 -
PTR
:逆向查询记录(Pointer Record),只用于从IP地址查询域名,详见下文。
6. DNS 报文结构
后面我将使用 wireshark 抓取 DNS 的数据包,但是在开始之前 ,得先了解一下 DNS 的报文结构
- 事务 ID:DNS 报文的 ID 标识。对于请求报文和其对应的应答报文,该字段的值是相同的。通过它可以区分 DNS 应答报文是对哪个请求进行响应的。
- 标志:DNS 报文中的标志字段。
- 问题计数:DNS 查询请求的数目。
- 回答资源记录数:DNS 响应的数目。
- 权威名称服务器计数:权威名称服务器的数目。
- 附加资源记录数:额外的记录数目(权威名称服务器对应 IP 地址的数目)。
7. Wireshark抓包实战
打开 Wireshark 后,使用 ping 163.com
来发起 DNS 解析请求,使用 DNS
关键字在Wireshark 过滤。
从抓取的报文整体来看,我们可以粗略获取几个信息
- DNS 是应用层协议,传输层协议使用的是 UDP
- DNS 默认端口是 53
请求和应答的报文的截图我放在了下面,接下来我将逐个分析。
请求
应答
Transaction ID
请求和应答的事务ID应当是一个:0xd0d7
Flags
标志字段里的内容比较多,每个字段的含义如下
- QR(Response):查询请求/响应的标志信息。查询请求时,值为 0;响应时,值为 1。
- Opcode:操作码。其中,0 表示标准查询;1 表示反向查询;2 表示服务器状态请求。
- AA(Authoritative):授权应答,该字段在响应报文中有效。值为 1 时,表示名称服务器是权威服务器;值为 0 时,表示不是权威服务器。
- TC(Truncated):表示是否被截断。值为 1 时,表示响应已超过 512 字节并已被截断,只返回前 512 个字节。
- RD(Recursion Desired):期望递归。该字段能在一个查询中设置,并在响应中返回。该标志告诉名称服务器必须处理这个查询,这种方式被称为一个递归查询。如果该位为 0,且被请求的名称服务器没有一个授权回答,它将返回一个能解答该查询的其他名称服务器列表。这种方式被称为迭代查询。
- RA(Recursion Available):可用递归。该字段只出现在响应报文中。当值为 1 时,表示服务器支持递归查询。
- Z:保留字段,在所有的请求和应答报文中,它的值必须为 0。
- rcode(Reply code):返回码字段,表示响应的差错状态。当值为 0 时,表示没有错误;当值为 1 时,表示报文格式错误(Format error),服务器不能理解请求的报文;当值为 2 时,表示域名服务器失败(Server failure),因为服务器的原因导致没办法处理这个请求;当值为 3 时,表示名字错误(Name Error),只有对授权域名解析服务器有意义,指出解析的域名不存在;当值为 4 时,表示查询类型不支持(Not Implemented),即域名服务器不支持查询类型;当值为 5 时,表示拒绝(Refused),一般是服务器由于设置的策略拒绝给出应答,如服务器不希望对某些请求者给出应答。
Answer RRs
回答资源记录数,在应答包里为 2,说明返回了两条查询结果,你可以在 Answer 字段里看到。
Authority RRs
权威名称服务器计数
Additionnal RRs
附加资源记录数
Answers
应答的主要内容,这里返回两条结果,每条结果里的字段有
Name: 查询的域名
Type: A表示IPv4,AAAA 表示IPv6
Class: 表示Internet,几乎总是它
Time to live: 生存时间
Data length: 数据长度
Address: 查询到的 IP 地址复制代码
8. DNS 劫持 与 HTTP 劫持
通过上面的讲解,我们都知道了,DNS 完成了一次域名到 IP 的映射查询,当你在访问 www.baidu.com 时,能正确返回给你 百度首页的 ip。
但如果此时 DNS 解析出现了一些问题,当你想要访问 www.baidu.com 时,却返回给你 www.google.com 的ip,这就是我们常说的 DNS 劫持。
与之容易混淆的有 HTTP 劫持。
那什么是 HTTP 劫持呢?
你一定见过当你在访问 某个网站时,右下角也突然弹出了一个扎眼的广告弹窗。这就是 HTTP 劫持。
借助别人文章里的例子,它们俩的区别就好比是
-
DNS劫持是你想去机场的时候,把你给丢到火车站。
-
HTTP劫持是你去机场途中,有人给你塞小广告。
那么 DNS劫持 是如何产生的呢?
下面大概说几种DNS劫持方法:
1.本机DNS劫持
攻击者通过某些手段使用户的计算机感染上木马病毒,或者恶意软件之后,恶意修改本地DNS配置,比如修改本地hosts文件,缓存等
2. 路由DNS劫持
很多用户默认路由器的默认密码,攻击者可以侵入到路由管理员账号中,修改路由器的默认配置
3.攻击DNS服务器
直接攻击DNS服务器,例如对DNS服务器进行DDOS攻击,可以是DNS服务器宕机,出现异常请求,还可以利用某些手段感染dns服务器的缓存,使给用户返回来的是恶意的ip地址
9. 工具的使用
dig 命令
dig是一个在类Unix命令行模式下查询DNS包括NS记录,A记录,MX记录等相关信息的工具。
通过 dig (参数:+trace
)命令,我们可以看到上面描述的 DNS 解析的详细过程
从返回的结果,我们可以看得出几点信息
- 我们的本地 DNS 服务器 ip 为 192.168.1.1,端口为53,你可以在 /etc/resolv.conf 里看到这个配置
- 根域名服务器目前全球一共只有十三台,从a.root-servers.net.
到
m.root-servers.net. ,它们对应的ip地址,已经内置在本地DNS服务器中。
如果你只想看到结果,可以使用 +short
参数,可以直接返回 www.163.com 对应着哪几个ip
你也可以加个 @
参数 ,指定从某个 DNS 服务器进行查询
如果你只想查看指定的记录类型
host 命令
host
命令 可以看作dig
命令的简化版本,返回当前请求域名的各种记录。
whois命令
whois
命令用来查看域名的注册情况。
nslookup命令
nslookup也是常用的一个查询 DNS 解析结果的工具
$ nslookup [查询的域名] [指定DNS服务器]复制代码
你也可以指定公网的域名服务器进行查询,比如常见的 114.114.114.114
10. 手动清理本地缓存
MacOS
$ sudo dscacheutil -flushcache
$ sudo killall -HUP mDNSResponder复制代码
Windows
$ ipconfig /flushdns复制代码
Linux
# 使用NSCD的DNS缓存
$ sudo /etc/init.d/nscd restart
# 服务器或者路由器使用DNSMASQ
$ sudo dnsmasq restart复制代码