先来简单介绍下 DNS (Domain Name System) , DNS 是一个协议,准确的说是一个基于 UDP 的应用层协议。主要用途是将一个域名解析成 IP 地址,这个过程叫做域名解析 (Name resolution)。
本文主要简单介绍下 DNS 的三种查询方式:
- 递归查询
- 迭代查询
- 非递归查询
我们把 DNS 查询当作一个故事的话,一个完整的故事需要有参与的角色和发生的事件
角色
Client
这里忽略浏览器以及操作系统,client 这里单纯的抽象表示一个请求者
DNS Server
除了发起请求的 Client,DNS 查询经过的别的节点基本都是 DNS 服务器
DNS Resolver
其实 Resolver 也是 DNS 服务器,但是它比较特别,我们把接受 Recursive Query 的 DNS 服务器称为 Resolver。很多 DNS 服务器处于性能考虑,不会接受 Recursive 请求,只接受 Iterative 请求,不能成为 Resolver
ISP (Internet Service Provider)
网络服务提供商,在中国的话就比如电信,网通等等
根域名服务器 (Root Name Server)
全球一共 13 台,负责返回顶级域 (.com 等) 的权威域名服务器地址
顶级域名服务器 (Top Level Domain Name Server)
负责返回一级域 (比如 example.com) 的权威域名服务器地址
权威域名服务器 (Authoritative Name Server)
负责返回其域名下的 Address 记录 (A record)
事件
递归查询 (Recursive query)
递归查询是这么一种查询方式,一般发生在 Client 请求 DNS Server。Client 发出一个域名解析的请求,DNS Server 必须返回对应的 IP 地址,或者返回找不到的错误。
迭代查询 (Iterative query)
迭代查询一般发生在 DNS Server 之间,当 Client 发出域名解析的请求后,DNS Server 需要给予最佳答案,这个最佳答案可能是"距离最近"的顶级域名服务器,也能是权威域名服务器。无论如何,Client 需要对返回结果再次发起请求,知道获得最终结果。
非递归查询 (Non-recursive query)
非递归查询发生在 Client 和 DNS Server 之间,指的是,请求的 DNS Server 已经知道答案,直接返回。这里可能有两种情况,一种是 DNS Server 本机缓存了对应的 IP,或者是缓存了对应的域名的权威服务器。第二种情况只需要再发一次请求,即可拿到结果返回。
故事
小明在 Laptop 的浏览器输入了example.com
,在没有任何缓存的情况下,laptop 作为 Client 向 Router 发出 DNS 递归查询请求,要求 Router 必须返回这个域名的 IP。Router 在什么都不知道的情况下,继续向 ISP 发起对 example.com
的递归查询,ISP 的 DNS server 在收到请求后,会依次对 Root Name Server,TLD Name Server,Authoritative Name Server 等发起迭代查询,最终返回我们要的结果。
其中根域名服务器会返回顶级域名服务器 (.com) 的 IP 地址,TLD 会返回 example.com 的权威域名服务器的 IP 地址,最后向 example.com 的权威域名服务器发起查询请求会得到最终的结果,即example.com 的服务器地址
可以看到这里在 Client 到 ISP 之间的 DNS 查询请求都是递归查询求,而 ISP 从根域名服务器开始的查询都是迭代查询。这样的查询方式的设计是为了保证性能,因为递归查询对服务器的压力要远大于迭代查询。
这里简单介绍下路由器这个角色,一般来说我们会使用 DHCP 协议,ISP 会给我们指定一个 DNS Server 作为 Resolver。但是因为我们使用路由器,路由器会拦截这个 DNS Server,同时分配路由器自己的 IP 作为我们计算机的 DNS Server。这样最后结果就是像上面说的,所有的 DNS 请求都通过路由器。当然我们可以自己指定计算机的 DNS 服务器,比如 Google 的 8.8.8.8,这样我们的 Resolver 就变成的指定的 DNS 服务器,而不会通过路由器。当然最好还是用路由器,因为路由器会替我们做缓存。