最近两周碰到了不同场景下四个DNS问题,所以记录一下
这几个Case描述如下:
- 一批ECS nslookup 域名结果正确,但是 ping 域名 返回 unknown host
- 在公司网下,我的windows7笔记本的wifi总是报dns域名异常无法上网(通过IP地址可以上网)
- Docker集群中两个容器中 nslookup 同一个域名,返回来的IP不一样
- 中间件的VipClient服务在centos7上域名解析失败
因为这些问题都不一样,但是都跟DNS服务相关所以打算分四篇文章挨个介绍,希望看完后DNS这块的问题应该是基本可以解决了。
nslookup 域名结果正确,但是 ping 域名 返回 unknown host
赶紧Google一下: nslookup ok but ping fail, 这个关键词居然Google自动提示了,看来碰到这个问题同学的好多好多
Google到的帖子大概有如下原因:
- 域名最后没有加 . 然后被自动追加了 tbsite.net aliyun.com alidc.net,自然 ping不到了
- /etc/resolv.conf 配置的nameserver要保证都是正常服务的
- /etc/nsswitch.conf 中的这行:hosts: files dns 配置成了 hosts: files mdns dns,而server不支持mdns
检查完我的环境没有上面的情况,比较悲催,居然碰到了一个Google不到的问题
那就抓包看为什么解析不了
DNS协议是典型的UDP应用,一来一回就搞定了查询,效率比TCP三次握手要高多了,DNS Server也支持TCP,不过一般不用TCP
sudo tcpdump -i eth0 udp and port 53
抓包发现ping 不通域名的时候都是把域名丢到了 /etc/resolv.conf 中的第二台nameserver,或者根本没有发送 dns查询。
这里要多解释一下我们的环境, /etc/resolv.conf 配置了2台 nameserver,第一台负责解析内部域名,另外一台负责解析其它域名,如果内部域名的解析请求丢到了第二台上自然会解析不到。
所以这个问题的根本原因是挑选的nameserver不对,按照 /etc/resolv.conf 的逻辑都是使用第一个nameserver,失败后才使用第二、第三个备用nameserver。
比较奇怪,出问题的都是新申请到的一批ECS,仔细对比了一下正常的机器,发现有问题的 ECS /etc/resolv.conf 中放了一个词rotate,赶紧查了一下rotate的作用(轮训多个nameserver),然后把rotate去掉果然就好了。
风波再起
本来以为问题彻底解决了,结果还是有一台机器ping仍然是unknow host,眼睛都看瞎了没发现啥问题,抓包发现总是把dns请求交给第二个nameserver,或者根本不发送dns请求,这就有意思了,跟我们理解的不太一样。
看着像有cache之类的,于是在正常和不正常的机器上使用 strace ,果然发现了点不一样的东西:
ping的过程中访问了 nscd(name service cache daemon) 同时发现 nscd返回值图中红框的 0,跟正常机器比较发现正常机器红框中是 -1,于是检查 /var/run/nscd/ 下面的东西,kill 掉 nscd进程,然后删掉这个文件夹,再ping,一切都正常了。
从strace来看所有的ping都会尝试看看 nscd 是否在运行,在的话找nscd要域名解析结果,如果nscd没有运行,那么再找 /etc/resolv.conf中的nameserver做域名解析
而nslookup和dig这样的命令就不会尝试找nscd,所以没有这个问题。
connect函数返回值的说明:
RETURN VALUE
If the connection or binding succeeds, zero is returned. On error, -1 is returned,and errno is set appropriately.
Windows下客户端是默认有dns cache的,但是Linux Client上默认没有dns cache,DNS Server上是有cache的,所以忽视了这个问题。这个nscd是之前看ping不通,google到这么一个命令,但是应该没有搞明白它的作用,就执行了一个网上的命令,把nscd拉起来,然后ping 因为rotate的问题,还是不通,同时nscd cache了这个不通的结果,导致了新的问题
原理分析
- DNS域名解析的时候先根据 /etc/nsswitch.conf 配置的顺序进行dns解析,一般是这样配置:hosts: files dns 【files代表 /etc/hosts dns 代表 /etc/resolv.conf】
- 如果本地有DNS Client Cache,先走Cache查询,所以有时候看不到DNS网络包。Linux下nscd可以做这个cache,Windows下有 ipconfig /displaydns ipconfig /flushdns
- 如果 /etc/resolv.conf 中配置了多个nameserver,默认使用第一个,只有第一个失败【如53端口不响应、查不到域名后再用后面的nameserver顶上】
- 如果 /etc/resolv.conf 中配置了rotate,那么多个nameserver轮流使用
总结
- /etc/resolv.conf rotate的关键作用
- nscd对域名解析的cache
- nslookup背后执行原理和ping不一样
- 在没有源代码的情况下strace和抓包能够看到问题的本质
下一篇介绍《在公司网下,我的windows7笔记本的wifi总是报dns域名异常无法上网(通过IP地址可以上网)》困扰了我两年,最近换了新笔记本还是有这个问题才痛下决心咬牙解决
参考资料
https://stackoverflow.com/questions/330395/dns-problem-nslookup-works-ping-doesnt