每个网民都应了解的DNS知识
本文旨在帮你深入了解DNS协议及其对Web性能的影响。
引言:DNS是什么?
域名如何转换成IP地址?
解析DNS通信
协议
报头
问题
应答资源记录
权威资源记录
额外记录
缓存是王道
NS缓存陷阱
设置TTL:平衡之道
单播VS任播
DNS故障和后备策略
我们认为,快速域名系统(DNS)的重要性完全不亚于快速内容。DNS负责将你熟悉的域名(www.google.com)转换成浏览器可以使用的IP地址(173.194.33.174)。这个系统对你网页的性能来说至关重要,不过大多数人并不完全了解其工作原理。
因此,为了帮你更深入地了解你网站的可用性和性能,本文旨在阐明有时很复杂的DNS世界,不妨从基本的说起。
在页面和页面上任何资源加载之前,DNS必须进行解析,那样浏览器才能建立一条TCP连接,提出HTTP请求。
此外,对于URL引用的每个外部资源而言,DNS解析必须完成同样的步骤(针对独特的域),之后才可以通过HTTP提出请求。用户在浏览器上输入URL地址、按回车键后,DNS解析过程就开始了。这时,浏览器向操作系统索要特定页面,这里是google.com。
第1步:针对DNS解析器的操作系统递归查询
由于操作系统不知道“www.google.com”在哪里,它会查询DNS解析器。操作系统发送到DNS解析器的查询有一个特殊标志(flag),告诉它这是“递归查询”。这意味着,解析器必须完成递归,响应不是IP地址就是错误。
对大多数用户来说,他们的DNS解析器是由互联网服务提供商(ISP)提供的,或者他们使用开源解析器,比如谷歌DNS(8.8.8.8)或OpenDNS(208.67.222.222)。这个在你的网络或路由器设置中可以查看或更改。这时,解析器完成了名为递归的过程,将域名转换成IP地址。
第2步:针对根服务器的DNS解析器迭代查询
解析器先查询其中一台根DNS服务器,获得“www.google.com”的IP地址。该查询没有递归标志,因而是“迭代查询”,这意味着其响应必定是地址、权威名称服务器的位置或错误。
有13个名为A-M的根服务器集群,服务器遍布380多个位置。根用域名末尾的隐藏尾部“.”来表示。输入这个额外的“.”没有必要,因为浏览器会自动添加它。
第3步:根服务器响应
这些根服务器保存所有顶级域名(TLD)和更新颖的通用TLD(gTLD)的位置,前者如.com、.de和.io,后者如.camera。它们由12家组织来管理,比如Verisign,这些组织负责向互联网号码分配机构(IANA)汇报,IANA控制着A集群和J集群。所有服务器都是由IANA运行的一台主服务器的副本。
根服务器并没有“www.google.com”的IP信息,但是它知道.com也许知道,于是返回com服务器的位置。根服务器会响应,列出.com gTLD服务器的13个位置,被列为NS即“名称服务器”记录 。
第4步:针对TLD服务器的DNS解析器迭代查询
下一步,解析器查询其中一台.com名称服务器,以获得google.com的位置。与根服务器一样,每个TLD都有位于许多地方的4至13台集群名称服务器。
TLD有两种类型:政府组织运行的国家代码顶级域名(ccTLD)和通用顶级域名(gTLD)。每个gTLD都有不同的商业机构负责运行这些服务器。在这里,我们将使用由Verisign控制的gTLD服务器,它们运行.com、.net、.edu和.gov。
第5步:TLD服务器响应
每台TLD服务器都有一份列表,列出了TLD中每个域的所有权威名称服务器。比如说,13台.com gTLD服务器每一台都有一份列表,列出了每一个.com域名的所有名称服务器。
.com gTLD服务器并没有google.com的IP地址,不过它知道google.com的名称服务器的地址。.com gTLD服务器会响应,列出google.com的所有名称服务器,每台服务器表示为NS即“名称服务器”记录。
第6步:针对Google.com NS的DNS解析器迭代查询
最后,DNS解析器查询其中一台谷歌授权名称服务器,以获得“www.google.com”的IP地址。
第7步:Google.com NS响应
这回,被查询的名称服务器知道IP地址,并响应,列出分别对应IPv4和IPv6的A或AAAA地址记录(取决于查询类型)。
第8步:针对操作系统的DNS解析器响应
这时,解析器已完成了递归过程,能够以IP地址响应最终用户的操作系统。
第9步:浏览器开始TCP握手
这时,操作系统现在有了www.google.com的IP地址,它将IP地址提供给应用程序(浏览器),浏览器建立TCP连接,开始加载页面。
如上所述,这是一种最坏情况。大多数情况下,如果用户最近访问了同一个域的URL,或者依赖同一DNS解析器的其他用户提出了此类请求,根本不需要DNS解析,或者会仅限于对本地DNS解析器的查询。
在这种DNS非缓存情况下,牵涉四台服务器,因而许多方面可能出错。最终用户不知道幕后发生的一切;他们只是等页面加载,所有这些DNS查询必须先行完成,之后浏览器才可以请求网页。
这就是为什么我们强调快速DNS的重要性。你可能有一个快速、制作精良的网站,但要是DNS很慢,网页响应时间仍会很糟糕。
现在你了解了递归过程,我们需要深入探究DNS的工作原理,之后进一步探讨DNS对性能会有怎样的影响。
在TCP/IP协议族中,DNS是一种应用层协议。默认情况下,DNS协议依赖用户数据报协议(UDP),不过防火墙阻止UDP时,它也可以通过传输控制协议(TCP)来工作,作为一条退路。
UDP和TCP都是传输层协议。UDP是一种轻量级协议,不需要握手就可以建立连接,也不需要确认已发送,因而减少了所需的数据包数量、所花时间和往返次数。UDP的最大缺点就是,无法保证数据包已被另一方收到,因而应用程序不得不处理响应未收到的情况。
另一方面,TCP需要通过分三步的握手来建立连接,拥有发送错误检查机制,不过需要更多往返次数,因而需要更长的时间。
由于我们探讨的是TCP/IP协议,在某些方面会深入到位层面。不过别害怕――你没必要学会如何处理“位标志”才能了解DNS。我们强烈建议使用Wireshark之类的数据包捕捉软件,让数据包易于读取,调试起来更容易。
协议
DNS协议由三种类型的消息组成:查询、响应和更新。我们在本文中不会探讨“更新”,因为它并不影响最终用户的体验。DNS消息可能有五个部分:DNS报头、问题、应答资源记录、权威资源记录和额外资源记录。
报头
数据包报头含有识别信息,以及关于消息其他部分所含内容的提示(摘要)。报头由六个字段组成,每个字段16位,共12个字节。前16位用于事务ID(Transaction ID),用来将响应与查询匹配,由查询消息端客户机创建,并由响应端服务器返回。
下一个字段用于标志。这可能是DNS数据包最重要的部分,因为这些标志区别响应和查询,区别迭代查询和递归查询。它们按顺序列出来:
第1位:QR(查询/响应)标志。若为0,消息是查询。若为1,消息是响应。
第2位至第5位:Opcode(操作码)。告诉接收端机器所发送消息的意图。通常来说,0意味着平常查询,不过还有其他有效选项,比如1表示反向查询,2表示服务器状态。
第6位:AA(授权应答)。只有响应机器是被查询域的授权名称服务器,才设置。
第7位:TC(截断)。如果数据包大于UDP的最大尺寸:512字节,才设置。
第8位:RD(期望递归)。若为0,查询是迭代查询。若为1,查询是递归查询。想了解更多信息,请参阅我们的递归那一章。
第9位:RA(可用递归)。如果服务器支持递归,在响应中将该位设置为1。
第10位:专门留给将来使用,针对所有查询和响应,必须设为0。
第11位:AD(真实数据)。用于DNSSEC中,被认为是旧机器中Z的一部分。
第12位:CD(检查禁用)。用于DNSSEC中,被认为是旧机器中Z的一部分。
第13位至第16位:Rcode(返回码)。如果域名不存在,它一般是0,表示错误。
剩余四个报头字段是问题数量、应答资源记录、授权资源记录和额外资源记录。这些数字不一样,取决于它是查询还是响应以及哪种响应。不过通常来说,总是至少会有一个问题。
问题
问题在查询和响应中都存在,应该一模一样。Wireshark等一些工具称问题为“查询”(参阅上图)。
通常来说,每个数据包只会有一个问题或查询。问题由三部分组成:查询名称(会是www.google.com之类的主机名称)、问题类型和问题类别(几乎总是1或IN,表示互联网)。问题类型是资源记录的类型。我们在此列出了几个主要类型,不过外面有更多类型。
A,IPv4地址:与域名对应。每个网站域名至少要有一个A记录,不然最终用户无法访问你的网站。
AAAA,四A,IPv6地址记录:IPv6地址是与域名对应的类型。由于IPv4地址不再可用,现在出现了积极支持IPv6的潮流――不过并非每家ISP和每个网站都支持IPv6。
MX,邮件交换记录:指定哪台邮件服务器代表域名接收方接受电子邮件消息。
NS,名称服务器记录:将域名及其授权名称服务器对应起来。每个域要有不止一个NS记录。
应答资源记录
应答由回答问题的资源记录组成。“Answer”部分出现在递归解析器针对最终用户计算机的响应上,或出现在授权名称服务器针对递归解析器域的响应中。它取决于问题类型,可是对Web域的DNS解析而言,它会是A、AAAA或CNAME。CNAME代表规范名称,这意味着查询中的域是另一个域的别名。
资源记录中的头三个字段与问题格式一样,包括资源记录名称、资源记录类型和资源记录类别。然而,资源记录含有三个额外字段、2字节生存时间值、单字节数据长度字段和数据字段。数据字段内容不一样,取决于记录类型,不过以下是主要内容:
A:存储4字节IPv4地址的一个数据字段
AAAA:存储16字节IPv4地址的一个数据字段
MX:两个数据字段,一个存储优先级值,另一个存储IP地址。
NS:存储授权名称服务器域名的一个数据字段
CNAME:存储作为问题域别名的域名的一个数据字段。
授权资源记录
如果TLD之类的名称服务器没有应答查询(因为不是授权服务器),它就不会发送应答记录。相反,它会往权威部分填入它知道对该域或域树(比如.com)一部分来说是权威的所有名称服务器,如果它有的话。
这些NS记录有别于A记录,因为它们在RR名称和RR数据字段中都有域名。不像应答部分,授权部分只能有NS记录。请注意:NS记录可以在其他部分中发送。
额外记录
额外或“粘合”记录提供在权威或应答部分中发送的NS记录IP地址(A或AAAA记录),那样那些域不需要解析,有助于避免额外递归。这些RR通常是权威部分中NS记录的A及/或AAAA记录,不过它们可以是任何记录。
不可否认,DNS解析过程(第一章已有介绍)异常漫长而复杂。
想想你在一天内访问多少个网站,然后考虑其中有几个多次访问。现在设想一下:每次访问,ISP在另一端的NS服务器就要从头开始重复整个递归过程,查询递归链中的所有名称服务器。
不妨想想你的手机。你想打电话给经常通话的朋友时,只要找到最近通话,然后按一下对方姓名。可是如果你拨打411查询电话号码,然后手动输入,而不是这个信息唾手可得,那会怎样?是不是似乎很繁琐?
事实上,将域名转换成IP地址需要好多步骤,因而需要好长时间。
幸好,DNS架构师们考虑了如何加快DNS,为此实施了缓存技术。缓存让任何DNS服务器或客户机都可以本地存储记录,以便将来重复使用,因而不需要新的查询。
域名系统在每个DNS记录上实施了生存时间(TTL)。TTL指定了DNS客户机或服务器缓存记录的秒数。如果记录存储到缓存中,与之伴随的任何TTL值也一并存储。
服务器继续更新存储在缓存中的记录的TTL,每秒钟倒计时。如果到0,记录从缓存中删除或清除。那时,如果收到该记录的查询,DNS服务器就得开始解析过程。
想了解缓存机制,不妨看看来自第一章的同一个例子:解析www.google.com。你在浏览器上输入www.google.com后,浏览器向操作系统索要IP地址。操作系统有所谓的“根解析器”(stub resolver)或“DNS客户端”,这种简单的解析器可以为操作系统处理所有的DNS查询。解析器会将查询(递归标志开启)发送到指定的递归解析器(名称服务器),并基于其TTL,将记录存储到缓存中。
根解析器收到来自应用程序的请求后,会先在缓存中查找;如果有该记录,它就将信息提供给应用程序。要是没有,就向递归解析器(ISP的DNS服务器)发送DNS查询(连同递归标志)。
“递归解析器”收到查询后,它会先在缓存中查找一番,看看有记录,它就将记录发送到“根解析器”。如果没有A记录,但有权威名称服务器的NS记录,之后它会查询那些名称服务器(绕过根服务器和.com gTLD服务器)。
如果它没有权威名称服务器,会查询gTLD服务器(极有可能在缓存中,因为TTL非常高,而且它们用于任何.com域)。只有不在缓存中,这种情况相当罕见(通常在全面清除之后),“递归解析器”才会查找根服务服务器,以获得gTLD。
虽说你无法控制ISP的DNS服务器的缓存,但可以管理你计算机的“根解析器”的缓存。排查DNS问题常常需要清除或清空DNS缓存。为此,在Windows中,只要打开命令提示符,输入ipconfig /flushdns,按回车键。在iOS上,你可以打开终端窗口,输入lookupd -flushcache。
为了防止过期的DNS记录传播,DNS服务器会将调整后的TTL传送到查询,而不是传送记录的原始TTL值。比如说,假设的A记录其TTL是4小时,并由“递归解析器”在早上8点存储到缓存。使用同一个解析器的新用户在早上9点查询同一个域时,解析器就会发送TTL为3小时的A记录。
到目前为止,我们介绍了DNS在操作系统和DNS服务器上如何缓存,不过,还有最后一层缓存:应用程序。任何应用程序可以选择缓存DNS数据,不过它们无法遵守DNS规范。应用程序依赖一种名为“getaddrinfo()”的操作系统函数,解析域(所有操作系统都有一样的函数名称)。该函数返回相应域的IP地址列表――但并不返回DNS记录,因而没有应用程序可使用的TTL信息。
因而,不同的应用程序将数据缓存一段特定的时间。IE10+会在其缓存中将最多256个域存储一段固定的时间:30分钟。虽然256个域看似挺多,其实不多――由于第三方标记和重新锁定,互联网上的许多页面引用50多个域。另一方面,Chrome会将DNS信息缓存1分钟,最多可存储1000个记录。
你可以访问chrome://net-internals/#dns,查看并清空Chrome的DNS缓存。
NS缓存陷阱
人们在DNS缓存方面常常掉入一大陷阱,那就是授权名称服务器记录。如前所述,授权名称服务器在查询响应中被指定为NS记录。NS记录有TTL,但并不提供名称服务器的IP地址。IP信息在响应的额外记录中,是A或AAAA记录。
因此,递归解析器依赖NS记录和A记录来抵达名称服务器。理想情况下,这两种记录上的TTL应该一样,但偶尔有人会错误配置DNS区。结果新记录覆盖旧记录,引起不一致。
如果两个记录都在缓存中,“递归解析器”会查询名称服务器的其中一个IP。如果“递归解析器”在缓存中只有NS记录,没有A或AAAA记录,就不得不解析授权名称服务器的域,以获得IP地址。
这不好,因为增添了解析相应域的时间。如果它有名称服务器的A或AAAA记录,却没有NS记录,它会被迫对www.google.com进行DNS查询。
设置TTL:平衡之道
那么,TTL设得长点好还是设得短点好?如果合适,使用更长的TTL,因为这会导致解析器和操作系统上有更长的缓存期――这对最终用户来说意味着性能更好,还为你的名称服务器减少通信量,因为它们会不常被查询。
然而,这也会削弱进行DNS更改的能力,让你更容易受到DNS投毒攻击,你的数据中心无法访问时,无法建立异地错误页面。
另一方面,更短的TTL限制了缓存,会给下载页面及/或资源增添时间,同时对名称服务器加大了压力。不过它们让你可以更快速地更改DNS配置。
DNS解析是个多步骤过程,牵涉互联网上的许多服务器。这种协议内置的缓存机制可将信息存储一段时间,为将来的DNS查询重复使用该信息,从而加快这个过程。
虽然DNS服务器及/或客户机确实遵守TTL方面的DNS规范,但浏览器等应用程序并不遵守该规范,因而它们的缓存可以存储任意一段时间。
现在不妨看一下任播(Anycast)及其最流行的对应技术:单播(Unicast),看看它如何缩短DNS响应时间。
几乎所有互联网和建立在其基础上的技术都依赖一种名为单播的路由方案。借助单播,每台服务器(或负载均衡系统后面的服务器集群)都有独特的IP地址,世界上任何一个设备都能依赖该地址与服务器进行联系。如果客户端设备在拓扑结构上靠近服务器,延迟就很小,应用程序的性能因而很高。但如果两者之间隔得很远,由于网络延迟,速度会相当慢。
将单播用于域名服务器时,你可以在全球有多台不同IP地址的物理服务器,依赖最终用户的解析器逻辑,抵达最近的那台名称服务器。解析器DNS服务器可以实施特殊逻辑,测量和存储它们查询的名称服务器的平均往返时间(RTT),然后优先使用RTT最短的那些服务器。然而,仍无法保证用户的DNS解析会很快。一些查询仍会发送到并不靠近解析器的名称服务器,不是所有解析器都启用这项功能以支持它。
在从我们在西雅图的第3层位置到单播IP地址的跟踪路由这个例子中,我们看到,它一路传输到位于纽约的本地服务器,增加了额外延迟。
任播
任播是可替代单播的一种路由方案。网络运营商使用边界网关协议(BGP),可以宣布来自分布全球各地的多个位置的同一个IP地址区间。这使得路由器可以将针对IP地址区间的流量引到宣布它的最近位置。我们运行来自西雅图的跟踪路由时,这回发送到任播IP地址,跳数、RTT和延迟都比较低:
任播方面有个地方要注意,那就是“最近”的定义。任播会路由到网络中拓扑结构定义为最少跳数的最近服务器。通常,拓扑结构靠近与地理位置靠近有着直接关联――但这并不意味着总是这种情况,也并不意味着延迟会最低。
路由方案背后的机制并不考虑延迟或地理。这意味着,如果你在亚特兰大,就跳数方面来说最近的任播服务器在达拉斯,但是地理位置最近的却在阿什本,你仍要路由到达拉斯,尽管RTT会更长。
除了提升性能外,任播还有另外几个好处:
充当多个接入点之间的第3层负载均衡系统,拥有自动故障切换机制。
可以通过放置地域分散的多个接入点,增添冗余性,从而提高可靠性。
加强抵御分布式拒绝服务攻击(DDoS)的能力,因为更难对多个分散的网络
位置发动此类攻击。
将攻击影响限制在特定地方,而不是整个系统受到影响。
任播的使用
任播主要用于依赖UDP协议(比如DNS)的应用程序。任播DNS已经被13台DNS根服务器中的12台所使用,并被大多数知名的DNS厂商(Cloudflare、Dyn、Edgecast和Verisign等)所使用。
对TCP协议而言任播比较难,因为连接必须保持状态,让日志保持有效。然而,越来越多的内容分发网络(CDN)在提供面向HTTP的任播解决方案。
虽然相比单播,任播安装和排查起来更难,但是任播DNS和HTTP服务有助于将快速网站变成超快速网站,因而改善最终用户的体验,满足网站营销计划的最重要方面之一。
DNS故障
现在应该很清楚:DNS服务器方面的故障或延迟会导致网站出现加载缓慢,或者在最坏情况下,导致网站完全无法使用。
大多数网站依赖第三方来满足DNS要求――通过域名注册机构的DNS服务器,或托管DNS提供商,避免自行构建和管理DNS服务器的成本和麻烦。把这交给第三方专家去处理是明智的策略,因为这通常降低了成本,提升了可靠性。不过与所有第三方提供商一样,其性能最终不受你的控制,即使你采取了所有必要的防范措施,它们有时还是会失败。
与所有第三方提供商一样,你应该与DNS提供商谈好服务级别协议(SLA),以免受到你无能为力的故障带来的经济影响。
遗憾的是,对DNS来说,后备策略成本高昂,因为完全处理故障的唯一办法就是让冗余服务(或你自己的基础设施)与你的主服务并排运行。很显然,这两种方法对大多数公司来说都成本高得吓人,因而SLA显得更重要了,因为你得能够捞回任何停运期间可能损失的收入。
挑战来自这一点:托管DNS提供商常常在全球各地的多个接入点有几百台服务器,这意味着“小型停运”可能局限于小范围地区,而无人察觉,可对对你网站的性能仍会有重大影响。
因此,就有必要制定一项高效的综合监控策略,万一你的DNS服务器出现故障或速度变慢,可以发现问题,并及时提醒。同时,实际用户度量(RUM)会更清楚地表明你的DNS性能在如何影响最终用户体验。不过值得一提的是,RUM无法让你深入了解DNS可用性,只有综合监控才能做到这点。
新闻来源:|云头条编译(未经授权谢绝转载)