当前位置: 首页 > 科技观察

DNS故障诊断与问题分析实例

时间:2023-03-12 09:25:05 科技观察

1.DNS基础知识Internet是基于TCP/IP协议的。为了便于管理网络中的主机,将整个Internet划分为若干个域,每个域又可以进一步划分为若干个子域。例如.com、.org、.edu都是顶级域名,而google.com是.com下的子域名。网络中的任何主机(host)都会属于某个域,并有自己的名字,称为主机名(hostname)。比如example.com就是.com域中一个名为example.com的主机(或者说主机名和域名的区别,看这里)。域名/主机名是为了方便人们的记忆,但是机器之间的通信仍然使用IP地址,所以需要一个将主机名(域名)转换成IP地址的服务。这就是域名服务系统(DNS,domainnamesystem)所做的,对应的服务器称为域名服务器(DomainNameServer)。例如,通过浏览器访问example.com时,浏览器首先会访问DNS服务器找到example.com对应的IP地址,然后与这个IP建立TCP连接,然后发起HTTP请求。一个域名可以对应一个IP地址,也可以对应多个IP地址。对于后者,DNS服务算法选择这些地址之一返回。为了实现高可用性,大多数网络服务都对应多个地址。后面我们会看到,baidu.com对应多个IP。有一些场景会导致访问DNS服务不稳定,比如DNS服务器设置问题、网络丢包、主机DNS配置错误等。接下来我们来看几个案例。2.准备测试环境。为了方便大家实践,本文将搭建容器环境。拉取Docker镜像:$sudodockerpullalpine:3.8运行容器,注意这里必须要加上--privileged参数[2],否则后面有些tc命令不会执行:$sudodockerrun-d--privileged--namectn-1alpine:3.8Sleep0d$sudodockerpsContainerIdimageCommandCoreatedStatusportsNames233bc36bde4Balpine:3.8“Sleep3600d”1minutesagoup14minutesctn-minutesctn-minutesctn-minutesctn-minterctn-1------14-14::172.17.0.9Bcast:0.0.0.0Mask:255.255.0.03、DNS配置3.1查看DNS配置Linux上的DNS配置在/etc/resolv.conf中。我们先查看一下容器的配置:/#cat/etc/resolv.conf#Dynamicresolv.conf(5)fileforglibcresolver(3)generatedbyresolvconf(8)#DONOTEDITTHISFILEBYHAND--YOURCHANGESWILLBEOVERWRITTENnameserver192.168.1.11nameserver192.168.1.12这个其实是继承来的主机的DNS配置,在主机上执行cat/etc/resolv.conf可以看到相同的结果。3.2修改DNS配置你可以通过修改/etc/resolv.conf中的nameserver来配置你想使用的DNS服务器。比如内网环境可能会使用自己的DNS服务器,因为它不仅提供内网域名解析,而且公网域名解析也会更快(相对于网络提供商的公网DNS服务器)。4.DNS故障排除本节模拟导致DNS查询速度变慢的几种情况。如果在实际环境中遇到类似现象,可以考虑从这几个方向排查。4.1机器上没有配置DNS,导致域名查找失败。问题现象:网络通了(比如pingIP),但是DNS查询总是失败。可能原因:机器没有配置DNS服务器。解决方法:修改/etc/resolv.conf给机器配置合适的DNS服务器有时候新启动的机器(无论是物理机、虚拟机还是容器)都没有设置DNS,导致无法访问域名。让我们重现它。在普通容器中,使用nslookup工具查看域名对应的IP地址:/#nslookupexample.comName:example.comAddress1:93.184.216.34Address2:2606:2800:220:1:248:1893:25c8:1946可以看到我们获取到了域名的一个IPv4地址和一个IPv6地址。用#注释掉/etc/resolv.conf中的DNS服务器列表,模拟没有配置DNS服务器的场景。再次测试:/#nslookupexample.comnslookup:can'tresolve'example.com':Tryagain所以如果遇到这种问题,可以先查看/etc/resolv.conf中是否配置了DNS服务器。4.2DNS服务太慢:DNS查询太慢可能原因:配置的DNS服务器不合理解决方法:修改/etc/resolv.用于解析内网DNS,可以加速公网域名的解析。dig是另一个更强大的DNS查询工具,安装:/#apkupdate&&apkaddbind-tools首先查看使用内网DNS查询域名的延迟:/#digexample.com...example.com.15814INA93.184.216.34;;Querytime:0msec;;SERVER:192.168.1.11#53(192.168.1.11)可以看出非常快,1ms以内。然后,我们测试了如果我们使用Google的公共DNS服务器8.8.8.8[1],延迟会是多少。修改/etc/resolv.conf,将其他nameservers注释掉,增加一行nameserver8.8.8.8。再次测试:/#digexample.com...example.com.15814INA93.184.216.34;;Querytime:150msec;;SERVER:8.8.8.8#53(8.8.8.8)延迟变成了150ms,比150ms大了之前多次。所以对于DNS查询特别慢的场景,首先要检查配置的DNS服务器是否合理。4.3Hardcode/etc/hosts导致DNS查询被跳过:域名访问速度太慢、域名总是指向同一个IP(多IP情况下)、特定机器无法访问域名等.可能原因:/etc/hosts有Hardcode域名和IP解决办法:修改/etc/hosts前面说到大部分公网域名对应多个IP地址,所以每次DNS查询得到的IP地址可能不同。我们用ping来测试一下:/#pingbaidu.comPINGbaidu.com(220.181.57.216):56databytes64bytesfrom220.181.57.216:seq=0ttl=45time=26.895ms64bytesfrom220.181.57.216:seq=1ttl=45time=26.701ms^uCcompingbaid^C123.125.115.110):56databytes64bytesfrom123.125.115.110:seq=0ttl=43time=27.587ms64bytesfrom123.125.115.110:seq=1ttl=43time=27.757ms^C可以看到,两次ping测试(内部先对应查询baidu.com获得的IP地址)不同。使用nslookup查看都是baidu.com对应的IP地址:/#nslookupbaidu.comName:baidu.comAddress:220.181.57.216Name:baidu.comAddress:123.125.115.110/etc/hosts可以直接硬编码一个域名对应的IPaddress,这样会导致本机跳过DNS查找,直接将这个IP作为域名的IP。让我们验证一下。修改/etc/hosts,添加一行123.125.115.110baidu.com,再次ping测试/#pingbaidu.comPINGbaidu.com(123.125.115.110):56databytes64bytesfrom123.125.115.110:seq=0ttl=43time=27.861ms^C---baidu.compingstatistics---1packetstransmitted,1packetsreceived,0%packetlossround-tripmin/avg/max=27.861/27.861/27.861ms/#pingbaidu.comPINGbaidu.com(123.125.115.110):56databytes64bytesfrom123.125.101tlt:q=36se4=2ms^C无论执行多少次,baidu.com对应的IP地址都不会改变。事实上,这个IP地址不一定是最优IP地址,甚至可能不可用,导致无法访问baidu.com。因此,在实践中尽量避免在/etc/hosts中进行硬编码。4.4DNS查询不稳定现象:DNS查询不稳定,时快时慢。可能原因:机器上有tc或iptables规则,导致到DNS服务器慢或丢包。解决方法:修改或删除tc/iptables规则。我们使用tc来模拟网络延迟:/#apkaddiproute2首先查看是否有tc规则:/#tc-pqdisclsdeveth0默认没有规则。然后我们添加一个:每个数据包延迟600ms:/#tcqdiscadddeveth0rootnetemdelay600ms/#tc-pqdisclsdeveth0/#qdiscnetem8001:rootrefcnt2limit1000delay600.0ms测试:/#digexample.com...example.com.15814INA93.184.216.34;;Querytime:60;;SERVER:192.168.1.11#53(192.168.1.11)可以看出DNS查询变成了600ms。这里测试的是固定延迟,这种问题很容易发现。我们还可以测试随机延迟,或者比例延迟等[2]:/#tcqdisccangedeveth0rootnetemdelay600ms10ms25%/#tcqdisccangedeveth0rootnetemdelay600ms20msdistributionnormal这样的规则会导致DNS查询速度更加随机。去掉最后的tc规则:/#tcqdiscdeldeveth0rootiptables规则也会出现类似的问题。很多软件运行后都会在宿主机上添加tc或者iptables规则,比如OpenStack、K8S等,所以遇到这种随机延迟的问题,可以先查看机器上是否有tc或者iptables规则。4.5DNS反向查询不稳定。我在网上遇到过这样一个问题:从一台机器上ping一个内网域名的时候,每个ping包好像都卡了5到30秒,但是CTL-C关闭ping之后,打印出来的统计信息里,没有丢包,而且ping延迟很低(毫秒级),很奇怪。接下来:dig,非常快,毫秒级别,说明DNS查询没有问题。dig可以看到域名对应的IP,直接ping这个IP,发现没有卡顿,但是还是ping域名,用tcpdump抓包,tcpdump-ieth0hostandicmp,发现ping包是全部立即响应,这证实了统计信息中ping延迟很低的事实。根据以上信息可以看出ping卡顿的问题是本机引起的,应该是ping程序本身耗时问题。手术。继续:依旧ping域名,同时使用ltrace-p跟踪ping过程,发现卡在了一个叫gethostbyaddr()的函数中。查阅文档,发现这个功能是根据IP反向查询hostname,需要和DNS交互。基本确定是DNS服务器的反向查找问题。让我们用其他几个命令行工具来验证它。下面三个命令是根据IP查看主机名:nslookuphostdig-x果然,以上三个命令都会卡死。修改/etc/resolv.conf,更换DNS服务器后,问题消失。接下来,让我们检查DNS服务器问题。