一道经典的面试题
从你在浏览器输入URL并按下回车到页面完整呈现都发生了什么?
这个问题可以回答的很复杂,gayhub上甚至有一个专门的仓库用来回答这个问题,从按下键盘的系统中断响应一直分析到浏览器如何解析渲染HTML文档。
我也准备在不断的学习过程中一步步地回答这个问题,当然我们不用从系统中断开始分析(笑
这篇文章将分析:DNS服务是如何将URL转换为IP地址的
什么是DNS
Domain Name System,简称DNS,译名:域名系统。
DNS有两重含义:
- 一个由分层的DNS服务器形成的分布式数据库
- 一个使得主机能够查询分布式数据库的应用层协议
关键词:分布式数据库,分层,应用层协议。
为什么要有DNS
回到开头提到的问题,我们输入了URL,那么URL是什么?
答:统一资源定位符,标记了internet中一个对象。一个对象只是一个文件,对应一个资源,如一份HTML文件,一张png图片,一段视频等。
举一个栗子🌰:http://www.somesite.com/somepath/somepic.png
这是一个URL,由两部分组成:
- 主机名
www.somesite.com
- 路径
/somepath/somepic.png
这个URL标记了一张存储于www.somesite.com
上、路径为/somepath/somepic.png
的图片。
我们想要请求这个URL以下载这张图片,那么问题来了。
对于我们人类来说这样的标记很好记,然而对于计算机来说,主机名几乎没有提供关于该主机在intenet中位置的信息。
并且因为主机名由不定长的字母和数字组成,路由器很难处理。
因此,主机可以使用IP地址进行标识。
IP地址(v4)由四个字节组成,并且有着严格的层次结构,当我们从左往右扫描IP地址,我们能得到越来越具体的该主机在internet中位置的信息。
对人类来说这个四字节的地址是很难记忆的。
而DNS提供了将主机名转换为其背后的IP地址的服务。
DNS提供的服务
当我们在浏览器的地址栏输入http://www.somesite.com/somepath/somepic.png
并按下回车,我们想要将一个HTTP请求报文发送到Web服务器www.somesite.com
,那么我们必须提供该服务器的IP地址,这时:
- 同一台主机上运行着DNS应用的客户端
- 浏览器从URL中取出主机名,传递给DNS应用的客户端
- DNS客户向DNS服务器发送一个包含主机名的请求
- DNS客户最终收到一份回答报文,其中包含目的主机的IP地址,并将该IP地址传给浏览器
- 浏览器向位于该IP地址80端口的HTTP服务器进程发起一个TCP连接
这就是DNS提供的主机名到IP地址转换的功能
除此以外DNS还提供以下服务:
- 主机别名。例如一台主机的主机名很难记,例如
oh-my-holy-shit.somename.com
,但它可能有一个或多个好记的别名(holyshit.com),这种情况下oh-my-holy-shit.somename.com
称为规范主机名,DNS提供从别名获取规范主机名和IP地址的服务。 - 邮件服务器别名。当我们日常使用邮箱时,例如`123456@qq.com
,真实的邮箱服务器主机名可能比
qq.com复杂到不知道哪里去了👓,此时的
qq.com`就是一个邮箱服务器的别名。DNS为电子邮件程序提供从别名到规范主机名的服务。 - 负载分配。一个IP地址的集合可能与一个规范主机名对应,DNS数据库中存储着这些IP地址,当查询该主机名的IP地址时DNS选择一个IP返回,这样就在这些服务器间分配了负载。
你可能意识到了,访问
qq.com
得到的并不是一个邮件服务器,那么是DNS对邮件服务和Web服务做了区分吗?后文将回答这个问题。
DNS工作机理概述
我们主要考虑从主机名获取IP地址的服务
从上文浏览器请求图片的例子可以看出,站在浏览器的角度,DNS是一个提供简单的转换服务的黑盒,然而这个黑盒内部非常复杂。
分布式、层次数据库
在我们对DNS的定义中提到:DNS是一个由分层的DNS服务器形成的分布式数据库。
为什么分布式
如今internet上有不计其数的主机,将它们的主机名与IP地址的映射统一管理,显然是不现实的,在维护、性能、硬件上有巨大的挑战,而且一旦出现故障整个internet都会崩溃。
何为层次式
上图中自顶向下三层,分别是:
- 根DNS服务器。级别最高的DNS服务器,返回顶级域(如
com
)的TLD服务器地址。根域名服务器地址的数量被限制为13个(标号为A到M),但实际上每个根域名服务器都是一个冗余服务器的网络。截至2017年11月,全球共有800台根域名服务器在运行。 - 顶级域DNS服务器。(Top-Level Domain,TLD)。负责顶级域名如com、org、net、edu、gov以及所有的国家顶级域名如cn、jp、uk。
- 权威DNS服务器。假设你成立了一家公司,公司的官网是
holyshit.com
。为了让人们能够用holyshit.com
这一域名访问你的网站,你可以自己架设一台DNS服务器,其中保存了holyshit.com
到IP地址的映射,这台服务器就是权威DNS服务器;你也可以付钱将这一映射保存到某个服务商提供的权威DNS服务器。
DNS服务使用大量的DNS服务器,它们以分层的方式组织,分布在世界各地。
全世界的主机名与IP地址的映射分布在这些DNS服务器上,并不存在一台保存了所有映射的服务器。
本地DNS服务器
这里的本地是指离你的主机足够近(通常几台路由器的距离),而不是运行在你的端系统。
每个ISP(大学,公司,居民区)都有一台本地DNS服务器,当某台主机发起DNS请求,该请求被发往本地DNS服务器,本地DNS服务器起一个代理的作用,然后本地DNS服务器将请求转发到上文所说的DNS服务器层次结构中。
一个具体的栗子🌰
假设我们要访问holyshit.com
,负责该主机名的权威DNS服务器为dns.holyshit.com
。
DNS查询的步骤分解如下:
- 请求主机向本地DNS服务器发送一个DNS查询报文,报文中包含要转换的主机名
holyshit.com
- 本地DNS服务器将该报文转发到根DNS服务器
- 根DNS服务器注意到
com
前缀,向本地DNS服务器返回负责com
前缀的TLD的IP地址列表 - 本地DNS服务器从返回的IP列表中选择一个,向该TLD服务器发送查询报文
- 该TLD服务器查询它的映射表,返回
holyshit.com
对应的权威DNS服务器IP地址,这个权威DNS服务器就是dns.holyshit.com
- 最后本地DNS服务器向
dns.holyshit.com
发送重发查询报文 dns.holyshit.com
用holyshit.com
的IP地址作为响应。- 本地DNS服务器向请求主机返回目标主机的IP地址
迭代查询与递归查询
上节的例子中,我们发现步骤二到步骤七,查询均由本地DNS服务器发出,共执行三次查询(实践中可能更多),每查询一次得到的结果都更加接近目标的IP地址。
每一次执行查询的主体都是本地DNS服务器,这种查询是迭代查询
。
至于递归查询,看一张图就一目了然了。
查询由主机发出,层层深入,在得到结果后层层返回,与递归的行为非常类似,因而称为递归查询。
上节的例子中从请求主机发往本地DNS服务器的查询就是一次递归查询。
DNS缓存
DNS广泛使用了缓存技术,在一个请求链中,当某DNS服务器收到了一个DNS应答(例如,主机名到地址的映射),它能将该应答存储在本地存储器中,这样当下一个请求该主机名的请求到来时它就能提供正确的IP地址,即使它并不是该主机名的权威服务器。
缓存保存的时间一般为两天。
本地DNS也可以保存TLD服务器的地址从而绕过根DNS服务器。
DNS记录和报文
存储在DNS这个分布式数据库中的内容称为资源记录(Resource Record,RR)
。
资源记录是一个包含了以下四个字段的四元组:
(Name, Value, Type, TTL)
TTL决定了记录被保存的时间,而Name和Value的值取决于Type:
Type | Name | Value |
---|---|---|
A | 主机名 | IP地址 |
NS | 域(foo.com) | 权威DNS服务器主机名 |
CNAME | 主机名 | 规范主机名 |
MX | 主机名 | 邮件服务器的规范主机名 |
DNS报文分为请求报文和回答报文。我们这里并不具体研究这两种报文的格式和字段。
在请求报文中会带上请求的主机名和请求的类型(对应RR的Type字段)
在回答报文中可以携带多个RR,因此一个主机名可以有多个IP地址(冗余服务器)。
至此可以回答上文中对于qq.com
并不是一个邮件服务器的疑惑:
在邮件服务中,DNS查询报文的类型字段为MX,因此查询到的RR与访问qq.com
时查询的RR并不相同。
EOF