陈鸽 阿里云智能GTS-SRE团队 技术专家

曾就职于微软负责Windows操作系统网络协议栈及网络产品技术支持相关工作,了解各产品标准协议例如TCPIP、DNS等。现就职于阿里云智能GTS-SRE团队,负责专有云网络相关产品(SLB/VPC等)的高可用、高可靠运维。

前言

现代系统大量依赖DNS提供的便捷的名称和IP映射关系来获取更好的适配性和稳定性(包括流量引导、均衡请求等功能),DNS的规范配置和使用变得越来越重要。因此,笔者将通过几篇系列文章来详细梳理下DNS的行为。

DNS客户端行为

目前主流两套操作系统,Windows和Linux,在DNS客户端的行为上各有不同。由于客户端是DNS请求发起的地方,我们详细梳理下各系统默认的DNS客户端行为。

  • Windows DNS Client service

    每个Windows系统都默认使用DNS Client service来处理名称解析请求,系统APIGetHostByName的调用在DNS Client service存在并启动的情况下,使用LRPC call将请求发往该服务内部处理;在DNS Client停用的情况下则直接使用Winsock的Namespace Provider直接解析(此时,行为与Linux的DNS请求类似)。

    因此,在Windows中,DNS名称解析的行为主要在DNS Client service存在的情况下发生,具体包括:

    • 检查DNS Client服务本地cache,如果命中缓存直接返回结果(包括negative result)。(注:hosts文件中的记录将会在我们修改hosts文件的时候由操作系统通知DNS Client服务重新加载hosts文件到DNS Client的缓存中)。
    • 如果缓存命中失败,第一次查询请求将发送给配置在主网卡上的PreferredDNS server。(注:在主机运行过程中会动态调整,默认我们认为主机开机后,第一个查询的服务器就是PreferredDNS server)。
    • 若前一步没有得到响应,一秒后,查询配置在所有网卡上的Preferred DNS server。
    • 同样的一秒后,查询所有网卡上的所有DNS server。
    • 此后,间隔两秒,四秒,八秒,再次查询所有DNS server,直到DNS Client内置的超时时间到期(约17秒)。

    注:若DNS Client查询发现服务器无响应,将会调整DNS server的顺序,避免下次查询继续发往无响应服务器。

  • Linux DNS Client

    Linux主机的DNS查询行为相对直接一些,大多数Linux主机默认不安装nscd,因此查询是直接进行而没有本地cache。

    根据/etc/resolv.conf的配置,gethostbyname API直接执行查询,具体包括:

    • 查询hosts文件。
    • 加载resolv.conf,根据nameserver配置,向第一个nameserver发送查询请求。
    • 若前一步没有得到响应,查询超时后(默认超时时间5秒),向下一个nameserver发起请求。
    • 轮询直至超过attempts配置。

    至于特有的domain/search/ndots/rotate(Linux),prefix/suffix/devolution(Windows)等等配置,可以在遇到具体问题的时候查询。

    注:在Windows/Linux中,DNS Client的查询总是recusive。它对DNS服务器的预期只是需要返回查询对应的结果(而非引用)。

  • 浏览器缓存

    其实这部分并不属于DNS客户端讨论范畴,但是由于现今浏览器的发展,浏览器已经包揽了越来越多的工作,在浏览器内部也已经出现了类似HTTP内容缓存的DNS缓存,在排查过程中不可忽视。

    chrome:about:net-internals/#dns
    firefox: about:networking#dns
    Chromium: about:net-internals/#dns
    IE/Edge: 暂无

客户端排查方案

从客户端的角度来看,一般我们需要知道客户端选择DNS服务器地址的逻辑,检查DNS查询名称生成的逻辑是否符合预期,以及是否从服务器的响应中得到了正确的结果。

在Windows上,我们主要通过DNS Client的ETL来追踪查询的行为。注意:Windows的内部调用比较复杂,我们需要追踪的组件较多,例如:

  • dnsapi.dll负责LRPC的CCALL和SCALL,在应用程序中以CCALL形式调用在DNS Client服务的SCALL名称解析功能。
  • dnsrslvr.dll负责名称解析功能,由dnsapi.dll SCALL调用,运行在DNS Client服务进程空间。
  • nslookup.exe摒除DNS Client服务调用,直接使用namespace provider执行名称解析。

更进一步可以追踪winsock相关组件和tcpip组件。DNS行为追踪工具有procmon,netmon,ETL trace(netsh.exe),DNS名称解析排查工具有nslookup.exe/dig.exe(需安装)。

本地cache检查:

ipconfig /displaydns
ipconfig /flushdns

在Linux上,可以通过strace来判断应用程序的名称解析行为,因为所有的名称解析操作都是直接在进程中调用gethostbyname来完成,在没有类似nscd缓存的情况下,所有名称解析行为发生在应用程序进程中。排查工具有strace,tcpdump,dig,nslookup。

结语

下期本文将介绍DNS客户端相关的排查方案,以及实际的案例,并根据实际经验总结DNS客户端的推荐配置,敬请期待!