说一下DNS执行流程? | Javaᶜⁿ 面试突击 (javacn.site)
为什么 DNS 协议使用 UDP?只使用了 UDP 吗? (qq.com)
DNS(Domain Name System,域名系统)是互联网中非常重要的基础设施之一,它负责将人类易于记忆的域名转换成计算机可识别的 IP 地址,使得用户可以方便地通过域名访问 Web 站点、发送电子邮件等。
使用nslookup工具进行DNS查询
nslookup // 交互式
在交互模式下正向解析,查询域名信息。要中断交互命令,可以使用ctrl + c组合键,要退出交互模式并返回到命令提示符,在命令提示符下输入“exit”即可。
nslookup [-option] [name | -] [server] // 非交互式
我们查询一个baidu.com
的命令结果如下
nslookup 后跟域名将显示域的“A 记录”(IP 地址)。使用此命令查找域的地址记录。它查询域名服务器并获取详细信息。
很多时候您会检查 A 记录以查看域的 IP,但有时您需要验证 IP 地址是否与特定域相关。为此,我们需要反向 DNS 查找。
DNS 实现原理
DNS 的流程可以看这张图:
浏览器访问了某个域名,首先会查找浏览器缓存、本地 hosts 文件、系统DNS缓存,没有找到的话再去请求本地 DNS 服务器,由它负责完成域名的解析。
本地 DNS 会依次请求根域名服务器拿到对应的顶级域名服务器的地址,然后请求顶级域名服务器,拿到权威域名服务器的地址,之后权威域名服务器会返回最终的 IP 给本地 DNS 服务器,由它再返给浏览器。
比如说 baidu.com
这个域名,根域名是.
,顶级域名(也叫一级域名)是 com
,而二级域名是 baidu.com
,那会先向根域名服务器查找 com
的顶级域名服务器的地址,然后再向 com
的顶级域名服务器查找 baidu.com
的权威域名服务器的地址。
有的同学可能会问,那 image.baidu.com
或者 xx.yy.zz.baidu.com
呢?
二级域名和更多级的域名都在权威域名服务器解析,域名服务器只有三级。
CDN 的实现原理
CDN 不是一种协议,只是基于 DNS 协议实现的一种分布式网络。
前面说到根域名和顶级域名服务器只是做了转发,最终域名解析都是在权威域名服务器做的。
那权威域名服务器是不是可以再做一层转发呢!!!
能不能在权威域名服务器这一层根据客户端的 ip 做一下负载均衡呢?比如北京来的 DNS 请求就返回北京机房的服务器的 ip,上海来的 DNS 请求就返回上海机房的服务器的 ip。
确实可以这样实现内容的就近分发,这样的负载均衡网络就叫做 CDN (Content Delivery Network)
但是实现这样一个 CDN 网络需要在全国建立多个机房,成本太高了,所以只有像百度、阿里、腾讯这类大公司才会自建 CDN,一般情况下我们都会买第三方的 CDN 服务来用。这些公司建好了 CDN 网络,实际上自己也是用不完的,也会对外提供 CDN 加速服务。
第三方的 CDN 服务自然也要提供一个 DNS 服务器,也就是实现根据 ip 返回不同城市的服务器的 ip 的那个。
比如这是百度云 CDN 的原理图:
用户向本地 DNS 服务器发请求之后,经历根域名、顶级域名的 DNS 解析,最终会转给权威 DNS 服务器。这时候只要权威 DNS 服务器再转给 baidu 的 DNS 服务器就可以了,这样就能接入 CDN 服务。
baidu 的 DNS 服务器实现了负载均衡,会根据请求 ip 所在的城市,返回不同城市的服务器的 ip。也就实现了就近分发的网络加速功能。
那这个从权威 DNS 到 baidu 的 DNS 的转发是怎么实现的呢?
DNS 的记录有很多种类型,比如:
-
A 代表 address,记录域名对应的 ip。
-
CNAME 代表域名还有一个别名,可以向那个域名来查 ip。
看到这个 CNAME 类型,大家应该就想到怎么实现转发了。
只要自己在 DNS服务器上配一条 CNAME 的记录,指向 CDN 服务器的域名就可以了。
比如你用某云的 CDN 的时候,第一步也是要配置下自己的 DNS 服务器的 CNAME 指向它:
这样,当你访问某个域名的时候,解析域名的权威服务器会返回 CDN 服务的 DNS 服务器的域名,然后再向这台 CDN 的 DNS 服务器发送解析域名的请求,这时候它就可以根据 ip 所在城市来返回一个就近城市的服务器给你。
这样客户端就能从最近的服务器下载静态资源,从而更快地打开网站。
如果访问的资源没有的时候,会向源站服务器发请求来拿对应的资源并且缓存下来,之后再此访问就不用访问源站了。
这个缓存时间是怎么指定的呢?
CDN 服务会有一个控制台,可以设置不同资源的缓存时间,当然,请求的 header 里也有 expries 和 Cache-Control 来控制缓存时间,这俩的生效的优先级也是可以设置的。
抓包验证上述结论
我们一步步来,首先,前面讲到这三级查找是对的么?
浏览器缓存和 DNS 缓存真的存在么?真的会查 hosts 文件么?
我们用抓包工具 Wireshark 来验证下:
抓取网卡的数据包,过滤 DNS 的包:
刷新页面就可以看到所有 DNS 数据包了:
然后你可以打开 chrome://net-internals/#dns
,查询某个域名的浏览器 DNS 缓存:
点击按钮可以清掉浏览器 DNS 缓存:
这证明了浏览器缓存的存在。
我们再往下验证,hosts 真的会生效么?
修改下 hosts 文件,加个配置:
用 ping 命令试了下,真的生效了,这说明 DNS 确实会查询 hosts 文件。
然后继续验证下系统的 DNS 缓存真的存在么?
我 ping 了几次 www.baidu.com
,都没有新的 DNS 数据包,说明确实是有缓存的。
可以执行这个命令清掉系统 DNS 缓存:sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder
我 ping 了两次 www.baidu.com
都没有 DNS 数据包,但是我一清空缓存,再 ping 就有了:
这验证了系统级别的 DNS 缓存确实存在。
也就是说浏览器 DNS 缓存、hosts 文件、系统 DNS 缓存这三步确实都是会经历的……
继续往下看,本地 DNS 服务是啥?
这个可以在“系统偏好设置 > 网络 > 高级”里看到:
确实是有本地 DNS 服务器的地址的,这个一般是运营商提供的,可能每个城市都有一些公共的。这一级也有缓存。
通过这层层缓存加上域名系统本身就是分布式的,这种设计极大的减轻了 DNS 服务器的压力,实现了高并发,这是我们每天都在用的高并发系统。
继续往后看,这三级域名服务怎么验证呢?
可以 ping 一个不存在的域名,比如 ddd1111.com
这时候可以看到请求了 com
的域名服务器,地址是 a.gtld-server.net
,没错,这个就是一个顶级域名服务器的域名。
但你再请求一个别的域名,你会发现它并没有从根域名顶级域名开始查,而是直接从权威域名服务器开始的:
没错,这也是缓存,本地 DNS 服务器会把域名对应的权威域名服务器的 IP 缓存下来,直接去那里查。
你会发现有的返回结果是 CNAME,值为一个域名,这个 CNAME 是一种记录类型,别名的意思。之后会再去这里查,最后查到 A 的记录类型,值就是 IP 了。
CDN 就是这么实现的,我们来看一个真实的 CDN 的 DNS 查询的例子:
这是 www.baidu.com
的 DNS 查询结果:
你会发现先通过 CNAME 指向了另一个域名,然后这个域名又给了两条 IP 的结果。
对照下 CDN 的原理图,就知道这俩 IP 都是离用户最近的服务器的 IP 了:
这就是 CDN 的原理。
再来看个 www.juejin.cn
的,他家也是用了 CDN 的:
也是同样 CNAME 指向了 CDN 的 DNS 服务器,然后返回了就近的一些服务器的 IP,只不过它的负载均衡的机器更多一些。
DNS是基于TCP还是UDP的?
为什么 DNS 协议使用 UDP 呢?这个问题可能大部分同学在各种博客或者面试过程中都或多或少遇见过,张口就来,UDP 快啊,DNS 使用 UDP 使得打开网页速度更快。
那各位有没有想过,既然 UDP 更快,为什么 HTTP 不使用 UDP 呢?
另外,为什么 DNS 协议使用 UDP 这个问题本身其实并不完全正确,DNS 并非只使用 UDP 协议,它同时占用了 UDP 和 TCP 的 53 端口,作为单个应用层的协议,DNS 同时使用两种传输协议也属实是个另类了。
DNS 为什么同时使用 TCP 和 UDP
我们从 TCP 与 UDP 的比较说起,老生常谈的话题,不过相信大部分同学都会忽略掉一个点,等下会指出来。
OK,轻松环节,闭着眼睛背:
1)TCP 需要三次握手建立连接,四次挥手释放连接;UDP 不需要,面向无连接
2)TCP 首部需要 20 个字节;而 UDP 首部只有 8 个字节
3)TCP 具有一系列保证可靠传输的机制;而 UDP 尽最大努力交付,不提供可靠传输的机制,如果在数据传输的过程中出现部分数据的丢失,UDP 协议本身并不能做出任何检测或补救措施
4)正是由于 UDP 没有了可靠传输机制,所以速度远远快于 TCP,在某些情况下 UDP 是一种最有效的工作方式,一般用于即时通信,比如:语音电话、 直播等等;而 TCP 一般用于文件传输、发送和接收邮件、远程登录等准确性要求比较高的场景
上面这些是最基本的吧。
接下来讲的这个点,也就是很多人容易忽略的点,和 DNS 为什么需要同时使用 UDP 和 TCP 这个问题息息相关:
- 那就是 TCP 是面向字节流的,而 UDP 是面向报文的
解释一下这句话,我们知道,TCP 具有序列号机制,发送方会把一个大的 HTTP 报文按序号分割成若干报文段并加上 TCP 首部,也就是封装成 TCP 报文段。那么接收方在收到这些 TCP 报文段后,就会按照序号以原来的顺序重组 HTTP 报文。这就是面向字节流的 TCP。
而所谓 UDP 面向报文,发送方的 UDP 对应用层交付下来的 HTTP 报文, 在添加 UDP 首部后也就是封装成 UDP 报文,就向下交付给网络层 IP 协议。不做任何的拆分与合并,主要就是因为 UDP 没有像 TCP 一样的序列号机制来标识报文,所以默认只有一个 UDP 报文。
UDP 这么做就会导致一个问题。
互联网上物理链路的最大传输单元 = 576 字节,为了在物理链路上顺利传输,UDP 报文不能超过 576 字节,为此,UDP 报文被限制在 512 字节以内。
而 DNS 由于大面积使用了 UDP,这样一旦 DNS 报文超过 512 字节,基于 UDP 的 DNS 报文就只有抛弃多出来的 64 字节,截短为 512 字节,那么用户得到的 DNS 报文就是不完整的。
如何解决这个问题呢?
没错,最简单的方式就是使用 TCP。尽管速度可能相之 UDP 较慢,但对于得到完整的 DNS 报文,速度慢一点也可以忍受。
DNS 分别在什么情况下使用 UDP 和 TCP
了解了 TCP 面向字节流而 UDP 面向报文的这个特性之后,在域名解析的时候,也就是客户端向 DNS 服务器查询域名获取 IP 地址的时候,DNS 协议关于 UDP 和 TCP 的选择通常可以分为以下两种情况:
1)若客户端事先知道 DNS 响应报文的长度会大于 512 字节,则应当直接使用 TCP 建立连接
2)若客户端事先不知道 DNS 响应报文的长度,一般会先使用 UDP 协议发送 DNS 查询报文,若 DNS 服务器发现 DNS 响应报文的长度大于 512 字节,则多出来的部分会被 UDP 抛弃(截断 TrunCation),那么服务器会把这个部分被抛弃的 DNS 报文首部中的 TC 标志位置为 1,以通知客户端该 DNS 报文已经被截断。客户端收到之后会重新发起一次 TCP 请求,从而使得它将来能够从 DNS 服务器收到完整的响应报文。
当然了,在域名解析的时候,一般返回的 DNS 响应报文都不会超过 512 字节,用 UDP 传输即可。事实上,很多 DNS 服务器进行配置的时候,也仅支持 UDP 查询包。
不过,DNS 不仅存在域名解析的过程,还有区域传输的过程,而在进行区域传输的时候 DNS 会强制使用 TCP 协议。
什么是区域传输?
这就不得不提一下主域名服务器和辅助域名服务器。
设置域名服务器时,服务器管理员可以选择将域名服务器指定为主服务器还是辅助服务器(也称为从服务器)。
主域名服务器负责维护一个区域的所有域名信息,是特定的所有信息的权威信息源,数据可以修改。主服务器直接从本地文件获取此信息。只能在主服务器上更改区域的 DNS 记录,然后主服务器才能更新辅助服务器。
当主域名服务器出现故障、关闭或负载过重时,辅助域名服务器作为主域名服务器的备份提供域名解析服务。辅助域名服务器中的区域文件中的数据是从主域名服务器中复制过来的,无法自行修改。
其实就是主从的概念,各位应该也都比较熟悉了。主域名服务器用来写,辅助域名服务器用来读,提供负载均衡的能力,缓解主域名服务器的压力。
那么所谓区域传输(zone transfer)呢,就是辅助域名服务器与主域名服务器通信,并同步数据信息的过程。
辅域名服务器会定时向主域名服务器进行查询以便了解数据是否有变动。如有变动,则会执行一次区域传输。区域传输使用 TCP 而不是 UDP,因为数据同步传送的数据量比一个 DNS 请求和响应报文的数据量要多得多。
文章开头提到的既然 UDP 更快,为什么 HTTP 不使用 UDP 呢?这个问题的答案也大抵如此。
由于互联网的不安全性,我们需要数字证书并携带数字签名来保证数据的安全性,为此,整个 HTTP 报文的大小已经远远超过 512 字节,无法使用 UDP 传输。
小结
综上,总结下,虽然 UDP 速度更快,DNS 协议也确实大面积使用了 UDP,但是由于 UDP 面向报文、只能传输小于 512 字节的特性,DNS 并非只使用了 UDP,具体的 TCP 和 UDP 使用场景如下:
- DNS 在域名解析的过程中,会根据 DNS 响应报文的大小选择使用 TCP 还是 UDP。但是一般情况下,返回的 DNS 响应报文都不会超过 512 字节,所以事实上,很多 DNS 服务器进行配置的时候,也仅支持 UDP 查询包;
- DNS 在进行区域传输的时候使用 TCP 协议。