Windows 名称解析的顺序 ── hosts、DNS 缓存、LLMNR/mDNS 与 DoH

· 更新日期: · · Windows, DNS, 名称解析, 网络, 故障排查, PowerShell, TCP/IP, IT 部门

「设置一样,偏偏这台电脑连不上内部服务器」「浏览器能打开,业务应用却名称解析失败」「写进 hosts 也没用」。

排查这类问题时,最先要确认的是是哪一套机制在回答这个名称。Windows 有缓存、hosts、DNS 服务器、LLMNR、NetBIOS、mDNS 这几条路径,而有些应用还会走与 Windows 不同的路径。

本文先建立整体图景,梳理名称的形态与各条路径的差别,再进入实际的排查步骤。想尽快开始调查的读者,可以从下表跳到对应位置。

遇到的问题 首先要确认的 阅读的位置
hosts 不生效/只有部分电脑返回旧 IP 缓存的内容,以及所用工具走的路径 缓存与 hosts步骤 2
app01 这样的短名称时,只有部分电脑失败 后缀补全,以及有没有 LLMNR 与 NetBT 名称的形态单标签名称的典型例子
一连 VPN 结果就变 多网卡的优先顺序与 NRPT 多网卡NRPT
等几秒就能连上 无响应的 DNS 服务器与重传时间 超时
浏览器和业务应用结果不同 内置解析器、安全 DNS、代理 应用的入口浏览器的 DoH
不知道该从哪查起 从名称的形态开始,限定路径逐一比较 排查步骤

本文的前提

项目 内容
目标读者 排查「解析不了名称」「只有部分电脑连不上」的 IT 部门人员,以及设计与维护业务应用通信的 Windows 应用开发者
前提知识 IP 地址与 DNS 的基础(A 记录、FQDN),能以管理员权限执行 PowerShell 的 cmdlet
前提环境 Windows 10 / Windows 11。DoH 一节需要 Windows 11 或 Windows Server 2022 及以上1。确认用的命令来自 DnsClient 模块(Windows 8 / Windows Server 2012 及以上)2
不涉及的内容 DNS 服务器一侧(Windows Server DNS 的区域、转发器、递归)的设置与故障。Zero Trust DNS(ZTDNS)的部署步骤

数据包捕获文章讲的是线路上流动的数据包,代理文章讲的是「读谁的代理设置」。本文则依据 Microsoft 的一手资料,梳理它们之前的那一步:「目标的 IP 地址是从哪里来的」。

1. 先说结论

要记住的是下面三点。

  • Windows 的名称解析并不总是沿着一条队列依次前进。缓存与 hosts 在前,但对单标签名称,默认情况下 DNS 与 LLMNR、NetBT 是并行工作的。34
  • 同一个名称,只要电脑的设置与应用的路径不同,结果就会不同。要把后缀、VPN、NRPT、浏览器的内置解析器分开考虑。567
  • 调查时要限定所用的路径再比较结果。Resolve-DnsName 的开关把缓存、DNS、链路本地分开,再通过与能连通的电脑做设置差分和抓包来确认。8

先把下面这张图当作整体的示意图来用。

名称解析是层的叠加名称解析的请求从应用的 API 交给 DNS 客户端服务,先看缓存与 hosts,接着是 DNS 服务器;只有单标签名称才会尝试 LLMNR、NetBIOS(默认与 DNS 并行)。对 .local 名称,除了已配置的 DNS 之外还会加上 mDNS 这条路径。浏览器在这条队列之外拥有自己的解析器没有则没有则・单标签名称(默认与 DNS 并行).local 名称(附加的路径)自有解析器・DoH应用(getaddrinfo)DNS 客户端服务缓存(含 hosts)向 DNS 服务器查询LLMNR / NetBIOSmDNS浏览器另一条路径

先看缓存,再往前是 DNS;若是单标签名称,LLMNR 与 NetBIOS 会并行工作。浏览器另有一条路径。

下面把「谁来回答」放在第 3~5 章,「怎么发送」放在第 6 章,「怎么确认」放在第 7~8 章。DoH 是把通往 DNS 服务器的传输通道换成 HTTPS 的功能,并不替换 hosts、缓存、NRPT 的顺序。9

图中实线表示始终成立的关系,虚线表示带条件的关系(成立条件写在详情页各关系的说明中)。关系的完整列表(共 48 条,附依据与确信度)以及主要概念的定义,汇总在知识地图详情页(日文)。数据:JSON-LD / Turtle

2. 「名称解析」不是一个单独的处理

返回给应用的只有地址或错误

当应用用 www.example.com 这样的名称去连接时,会调用 Winsock 的 getaddrinfo(Unicode 版是 GetAddrInfoW)。这个函数针对 NS_DNS 命名空间,通过 DNS、本地的 hosts 文件以及其他机制把名称转换成地址。若有多个命名空间提供程序响应,它会汇总后返回。10

也就是说,应用只是收到了结果,并不知道是哪一层回答的

.NET 的 Dns.GetHostAddresses 在 Windows 上同样使用 getaddrinfo。对于写在 hosts 里的主机,它不会去问 DNS 服务器就直接返回那个地址。HttpClient 也建立在这个 Dns 类之上,因此直接连接目标的 .NET 应用会继承 Windows 的名称解析顺序。11

经 HTTP 代理时,被解析的名称会变。在本地解析的是代理的名称,目标的名称由代理一侧解析。这种情况下,本地的 hosts、缓存、后缀、NRPT 都不参与目标的解析。具体使用哪套代理设置,在代理文章中有讲。

2.1 DNS 客户端服务决定顺序

getaddrinfo 之下工作的是 DNS 客户端服务(服务名 Dnscache)。Microsoft 的资料把基本顺序说明如下。3

  1. 查看缓存。
  2. 查看 hosts 文件。
  3. 向 DNS 服务器查询。

由于 hosts 的内容会在服务启动时读入缓存,本文把前两项合起来当作第 1 层「缓存与 hosts」处理。5

再往后,就要看名称与策略了。

职责 读顺序时的注意事项
第 1 层: 缓存与 hosts 返回电脑内部已有的答案 这里出了答案就不会去问 DNS 服务器
第 2 层: DNS 服务器 通过向 DNS 查询得到答案 涉及后缀、多网卡、NRPT 等
第 3 层: LLMNR・NetBT 用另外的手段解析单标签名称 默认与第 2 层并行。只有停用优化时才会在 DNS 失败后串行

默认的「智能多宿主名称解析」会把 DNS、LLMNR、NetBT 的查询并行发往所有网络。采用哪个响应,由 4.3 节与 5.2 节的规则决定。4

因此,「什么时候发出查询」和「返回的答案按什么优先顺序采用」是两回事。抓包里看到 LLMNR 或 NetBT,并不能仅凭这一点就说「DNS 失败了」。本文的「三层」是为了梳理而做的划分,并不意味着它们总是按时间顺序串行工作。

2.2 处在队列之外的东西

特别容易混淆的是下面两个。

工具・应用 与 Windows 路径的差别 调查时的注意事项
nslookup 不使用操作系统的解析器,绕过缓存、hosts、NRPT,直接问第一台 DNS 服务器123 ping 或业务应用结果不同并不奇怪
Microsoft Edge 默认使用内置 DNS 客户端。DoH 也始终由内置解析器处理7 「浏览器能打开」不能证明操作系统的名称解析是健康的

使用 Edge 的内置客户端本身并不意味着更换了 DNS 服务器。这与选择别的提供商的安全 DNS 设置要分开,我们在 6.2 节确认。

3. 第 1 层 ── 缓存与 hosts

这一层想知道的是电脑内部还留着什么样的答案。缓存里不仅有正确的答案,也会留下旧的答案和「没有这个名称」的答案。

3.1 hosts 会被读入缓存

hosts 文件位于 C:\Windows\System32\drivers\etc\hosts。DNS 客户端服务启动时,名称与 IP 地址的对应会被读入解析器缓存。通过 DNS 查询得到的记录,也会在 TTL(生存时间)期间保存在同一个缓存中。5

ipconfig /displaydns 会同时显示从 hosts 读入的条目和最近的 DNS 查询得到的条目。13 Microsoft 的示例中也是:只要在 hosts 里写上 contoso.comResolve-DnsName contoso.com 就会返回那个地址,不会有 DNS 通信流出。3

看不到 DNS 数据包时怎么读

在没有 DoH、DoT 的情况下查询 FQDN,名称解析成功却没有 53 端口的查询,那多半是缓存或 hosts 给出了答案。不过要先排除下面这些其他路径。

名称・设置 除 53 端口外要确认的通信
.local 名称 mDNS(UDP 5353)
单标签名称 LLMNR(5355)、NetBT 的名称服务(UDP 137)
启用了 DoH HTTPS(443)
启用了 DoT TLS(853)

不要只凭「没有 53 端口」就断定是缓存,要把可能被用到的路径一并看过。开发机上残留的一行验证用 hosts,也可能把调查带偏。

编辑 hosts 需要管理员权限,安全产品有时还会检测到这类更改。应当避免让业务应用的运维依赖 hosts 的设计。

3.2 否定响应也会被缓存

「没找到」也是会被缓存的答案之一。DNS 客户端不仅保存肯定响应,也保存否定响应。5

如果 ipconfig /displaydns 中对应名称显示为「Name does not exist」,说明 DNS 服务器的否定响应还留在客户端上。Microsoft 的步骤是用 ipconfig /flushdns 把它丢掉。1413

否定缓存的保留时间由 HKLM\SYSTEM\CurrentControlSet\Services\Dnscache\ParametersMaxNegativeCacheTtl 决定,默认是 5 秒。15 在 DNS 中刚加完记录,那台电脑仍会在几秒内返回失败,原因就在这里。

3.3 TTL 与「只有部分电脑是旧的」

肯定响应也会在 TTL 期间留存。在更改服务器 IP 地址之前查过这个名称的电脑会继续用旧答案,而更改之后才第一次查询的电脑则会得到新答案。即使用的是同一台 DNS 服务器,查询的时刻不同结果就不同。5

Clear-DnsClientCacheipconfig /flushdns 行为相同,会删除包含否定响应在内的全部缓存内容。16Get-DnsClientCache 则可以把缓存作为对象取出,查看记录类型和剩余 TTL。17

# 某个名称是否在缓存中,剩余 TTL 是多少秒
Get-DnsClientCache -Entry 'app01.corp.example.com' |
    Select-Object Entry, Type, Status, TimeToLive, Data

# 一并查看 hosts 与缓存的内容
ipconfig /displaydns | Select-String -Pattern 'app01' -Context 0,6

# 丢弃缓存(包括否定响应)
Clear-DnsClientCache

只要第 1 层给出答案,这次查找在到达 DNS 服务器之前就已经定了。不过,错误的答案原本就是从 DNS 服务器学来的这种可能性仍然存在。不要删完就收工,还要按第 8 章的步骤 3 确认重新取得的答案。

4. 第 2 层 ── 向 DNS 服务器查询

第 1 层没有答案就前进到 DNS。这里要把用什么名称、发往哪台服务器、在什么时机发送分开来考虑。

4.1 单标签名称与后缀

首先确认应用交过来的名称是什么形态。5

名称的形态 例子 发往 DNS 的方式
末尾带点的 FQDN(绝对名称) www.contoso.com. 原样发送
含点但末尾没有点的名称 www.contoso.com 默认在末尾加点后发送。如果启用了允许给多标签名称附加后缀的策略,也会尝试后缀4
不含点的单标签名称 www 用电脑的后缀设置补全后发送

后缀就是补在短名称后面的域名部分。给 app01 加上 corp.example.com,查询的名称就成了 app01.corp.example.com

有搜索列表的情况

从 DNS 后缀搜索列表的开头依次附加后缀,并发送末尾加了点的名称。一旦配置了搜索列表,就只会使用这个列表。主后缀、连接特定后缀以及名称降级都不会被使用。18

没有搜索列表的情况

附加主 DNS 后缀后发送。如果启用了名称降级(devolution),每失败一次就去掉最左边的标签再试。例如从 www.test.contoso.com 前进到 www.contoso.com。若适配器有连接特定的 DNS 后缀,也会附加它发送。5

因此,在用组策略下发搜索列表的环境和靠加入域获得主后缀的环境中,同样是 server01,展开结果也不同。

长列表也会增加等待时间

如果正确的后缀排在列表靠后的位置,到达它之前的查询时间就会累积起来。Microsoft 也用尝试 6 个后缀的例子说明了这种延迟。若只想尝试某个特定的展开结果,就像 internal.contoso.com. 那样在末尾加点。3

# 全局设置: 搜索列表与降级
Get-DnsClientGlobalSetting

# 按接口: 连接特定后缀与注册设置
Get-DnsClient | Select-Object InterfaceAlias, ConnectionSpecificSuffix, UseSuffixWhenRegistering

# 按接口的 DNS 服务器(IPv4 与 IPv6 两者)
Get-DnsClientServerAddress | Where-Object ServerAddresses | Select-Object InterfaceAlias, AddressFamily, ServerAddresses

Get-DnsClientGlobalSetting 返回搜索列表、是否降级及其级数等全局设置,Get-DnsClient 返回按接口的设置。1920

4.2 多台 DNS 服务器的顺序与超时

当出现「不失败但要等几秒」时,就该怀疑是向无响应的 DNS 服务器重传。对配置在一块网卡上的 DNS 服务器,把默认的重传时机排出来是这样的。21

从开始起 1 台配置 2 台配置 3 台及以上配置
0 秒 向服务器查询 向第 1 台 向第 1 台
1 秒 重传 向第 2 台 向第 2 台
2 秒 重传 向第 2 台重传 向第 3 台
4 秒 重传 同时向全部服务器 同时向全部服务器
8 秒 重传 同时向全部服务器 同时向全部服务器
10 秒 放弃 放弃 放弃

这是没有响应时的表。特别不要把下面两者混为一谈。

服务器的反应 是否尝试下一台服务器 怎么读
无响应 尝试 重传与超时的问题
返回「没有这个名称」的否定响应 到此为止 已经收到了「没有这个名称」的答案

当「停掉了一台却没有切换过去」时,如果一台持有旧区域的服务器仍在运行并返回否定响应,就不会往下走。21

第 4 位及以后的服务器,要等 4 秒之后才轮到

如果能响应的服务器排在列表第 4 位及以后,那么从第一次查询算起至少要等 4 秒。若应用的期限比这更短,就会在名称解析阶段失败。想让查询提前,就得把它挪到前 3 位中的某一位,但根本对策是修好前面那台不通的服务器,或者把它从设置中去掉。同时也要重新审视应用一侧的超时。21

Microsoft 的示例中,4 台里只有 1 台可达的配置,完成也要约 4 秒。可以用 Measure-Command 测耗时,该资料把 1 秒以内视为可接受范围。3

# 只用 DNS 直接问某台服务器,并以毫秒得到耗时
(Measure-Command {
    Resolve-DnsName -Name 'app01.corp.example.com' -Server 10.0.1.2 -DnsOnly
}).TotalMilliseconds

这条命令固定了服务器,因此测的是那台服务器单独的响应时间。到达列表第 4 位之前的延迟,要用不带 -Server 的查询或它的抓包来确认。

另外,DNS 客户端会把响应快的服务器往上挪,并记住无响应的服务器定期重试。首次超时也会根据过去的实绩在 25~1,000 毫秒的范围内调整。上表只是默认的骨架,实测有偏差正是因为如此。5

4.3 多网卡与「智能多宿主名称解析」

在同时拥有有线与 Wi-Fi 的电脑,或者又加上 VPN 适配器的电脑上,除了 DNS 服务器的列表,还要确认网络之间的查询与响应的选择

向多个适配器重传

在 Microsoft 的查询流程中,先向首选适配器的第一台 DNS 服务器发送并等 1 秒。没有响应就向仍在候选中的全部适配器的第一台服务器发送并等 2 秒,之后向全部适配器的全部服务器发送,等待时间依次取 2 秒、4 秒、8 秒。某个适配器的服务器返回否定响应时,该适配器的其他服务器就退出候选。5

控制并行查询的策略

组策略「关闭智能多宿主名称解析」控制的是下面这些行为。4

策略 行为
默认(未配置) 把 DNS、LLMNR、NetBT 并行发往所有网络。若有多个肯定响应,按网络的绑定顺序采用
已启用 停止该优化。先在所有网络上尝试 DNS,失败后是 LLMNR,再失败是 NetBT,变成串行

这项策略的名字是「关闭…」,所以要注意启用策略等于停用该优化

VPN 改变结果的例子

查询内部名称时,VPN 一侧的 DNS 返回内部地址,而家里路由器一侧的 DNS 也可能返回另一个肯定响应。比如与内部同名域名的公网地址,或是把不存在的名称替换成广告页面的地址。

有两个肯定响应时,采用哪一个由绑定顺序决定。在现今的 Windows 上,这个优先顺序由接口跃点数决定,Get-NetIPInterfaceInterfaceMetric 越小越优先。各台电脑顺序上的差异,就变成了结果上的差异。22

另一方面,如果家里一侧返回否定响应,那么该适配器会退出候选,采用 VPN 一侧的答案。5 VPN 产品之所以下发 NRPT 或「关闭智能多宿主名称解析」,正是为了控制这类差异。

4.4 NRPT ── 按命名空间改变查询目标

NRPT(Name Resolution Policy Table,名称解析策略表)是一张表,按 .corp.contoso.com 之类的命名空间指定要使用的 DNS 服务器以及 DirectAccess、DNSSEC 的设置。DirectAccess 与 Always On VPN 的配置文件会写入规则,做出「只把内部名称指向内部 DNS」这样的行为。236

Get-DnsClientNrptPolicy -Effective 可以确认实际生效的规则。

# 实际生效的 NRPT 规则
Get-DnsClientNrptPolicy -Effective

# 只显示特定命名空间的规则。-Namespace 只按 Namespace 属性筛选,不做与名称的匹配判定。
# 传入 'app01.corp.example.com' 也不会返回 '.corp.example.com' 的后缀规则。
# 某个名称由哪条规则生效,要像第 8 章步骤 4 那样自己列举规则并比对
Get-DnsClientNrptPolicy -Effective -Namespace '.corp.example.com'

NRPT 只对使用 Windows DNS API 的应用生效。自带 DNS 实现的应用会绕过那条路径。VPNv2 CSP 的资料以 nslookup 为例,要求确认 NRPT 时使用 Resolve-DnsName。浏览器的内置解析器和 DoH 同样在 Windows DNS API 之外。6

5. 第 3 层 ── 单标签名称的退路: LLMNR、NetBIOS,以及 mDNS

5.1 三种协议的差别

LLMNR 与 NetBIOS over TCP/IP(NetBT)是解析 app01 这类单标签名称的另外手段。默认与 DNS 并行工作,即使 DNS 返回了肯定响应,也可能采用链路本地的响应。只有停用了智能多宿主名称解析时,才会变成 DNS 失败后的串行。4

mDNS 与此不同,它是加在 .local 名称上的一条路径。它不是单标签名称的 DNS 解析失败之后的兜底。24

协议 端口 到达范围 定位
LLMNR UDP 5355 的组播。TCP 5355 用于单播重传2526 同一子网内的链路 不配置 DNS 也能用的次要名称解析4
mDNS UDP 5353 的组播24 组播能到达的本地网络 解析 .local 名称。Microsoft 选定的今后主轴27
NetBT UDP 137 的名称服务28 广播,或向 WINS 服务器查询29 遗留技术。推荐从 WINS 迁移到 DNS30

即使是 .local,也别跳过 DNS 的确认

.local 并不会变成 mDNS 专用。当 Active Directory 域是 corp.local 之类时,这个名称仍会由已配置的 DNS 服务器或 NRPT 解析。RFC 6762 也认可与单播 DNS 并用。调查 .local 名称时,同样要确认 DNS 与 VPN 的策略。24

NetBT 会随 WINS 的有无与节点类型而变

节点类型 名称解析的方式
B-node 仅广播
P-node 仅向 WINS 查询
M-node 先广播后 WINS
H-node 先 WINS 后广播

未配置 WINS 时默认为 B-node,只要配置了一台就默认为 H-node。29 LLMNR 与 NetBT 的广播不能跨越子网,但向 WINS 的查询是单播,因此可以跨越。

nbtstat -c 可以显示 NetBIOS 名称缓存,用 nbtstat -R 可以清除缓存并重新读入 LMHOSTS。31

5.2 哪一个优先

并行查询之后,优先采用哪个响应也会随策略变化。4

条件 单标签名称的响应优先顺序
默认・不属于域的网络 LLMNR 与 NetBT 的链路本地响应优先于 DNS
域的网络 DNS 响应优先
启用「关闭智能协议重新排序」 在所有网络上按 DNS→LLMNR→NetBT 的顺序优先

在家里或外出时的网络上,附近同名设备的答案有可能优先于 DNS。这里同样重要的是,把响应的优先顺序与查询是串行还是并行分开来读

5.3 Microsoft 的方针: 向 mDNS 靠拢

Microsoft 在 2022 年 4 月公布了向 mDNS 靠拢、逐步收缩 NetBIOS 名称解析与 LLMNR 的方针。27 像 Computer Browser 这类古老且不安全的设备发现协议也已被弃用。32 用组播或广播来补足单标签名称的设计,正在朝着收缩的方向走。

关于 LLMNR 漏洞的 Microsoft 信息中,把阻断 TCP/UDP 5355 以及启用组策略「关闭多播名称解析」列为规避措施。同时也明确写出其影响:计算机可能不再被其他计算机看到。25 启用这项策略后,DNS 客户端的所有适配器上 LLMNR 都会被停用。4

停用这个方向本身是正确的判断,但必须在 DNS 中为消失的那条路径准备替代。未在 DNS 登记的设备要登记 A 记录,或者启用通过 DHCP 的动态注册,并把目标改成 FQDN。支持 mDNS 的设备可以用 .local 名称,但到达范围仅限组播能通的范围。

5.4 「只有部分电脑连不上」的典型: 单标签名称

当配置文件或快捷方式里写着 \\fileserver01http://app01/ 时,同一个名称也会出现下面这些差别。

电脑的环境 可能发生的情况
加入域的台式机 被后缀补全为 app01.corp.example.com,可由内部 DNS 解析
经 VPN 的笔记本 补全与否取决于 VPN 配置文件。若没有补全,且同一子网内也没有对象,LLMNR 与 NetBT 就会落空
位于其他子网的办公室 若 DNS 中没有登记,LLMNR 与 NetBT 的广播就到不了。不过若 WINS 中有登记,有时仍可解析2930
同时停用了 LLMNR 与 NetBT 的电脑 DNS 里没有的名称就解析不了。若只停用 LLMNR,还留有用 NetBT 或 WINS 解析的余地

Resolve-DnsName app01 -LlmnrOnly 能知道的是「能否用 LLMNR 解析」,并不能知道平时的查询采用的答案出自哪里。与不带开关的结果做比较以及抓包,放在第 8 章的步骤 5 里做。8

根本对策是 FQDN 化与 DNS 登记

把依赖单标签名称的目标改成 FQDN,把名称解析集中到 DNS。

SMB2 及以上通过 TCP 445 直接连接,不使用 NetBIOS 的会话。33 但那说的是传输通道。在解析 \\fileserver01\share 这个目标名称的阶段,仍可能用到 LLMNR 或 NetBT。像 \\fileserver01.corp.example.com\share 这样用 FQDN 指定,才能摆脱对单标签名称路径的依赖。

不过 FQDN 也仍有下面几点需要注意。末尾没有点的 FQDN,在启用了给多标签名称附加后缀的策略时也会被尝试补全。以 .local 结尾的名称有可能并用 mDNS。要无条件固定,绝对名称要写成末尾带点的形式。实务上把「FQDN 就会固定在 DNS 上」当作前提,成立的条件是上述策略未启用,且内部域名没有使用 .local

6. 通往 DNS 服务器的传输通道 ── DoH 不改变顺序

6.1 Windows 11 / Windows Server 2022 的 DoH

Windows 的 DoH 是把发往 DNS 服务器的查询用 HTTPS 送出的功能。它与既有的 hosts、缓存、NRPT,以及按适配器、按配置文件指定解析器的机制整合在一起,并不替换第 3~4 章的顺序。9

Windows 11 的 DNS 客户端支持 DoH,较新的版本还支持 DoT(DNS over TLS)。不过 Microsoft 的说明没有写明 DoT 的支持版本,所以未必在本文的全部前提环境中都能使用。下面只讲 DoH。9

首先确认已知 DoH 服务器清单

在没有启用 DDR 的情况下,能用的是列在已知 DoH 服务器清单上的服务器。默认清单里有 Cloudflare、Google、Quad9,可以用 Get-DnsClientDohServerAddress 确认。内部 DNS 之类需要登记 DoH 模板以及回退与自动升级的设置。134

# 已知 DoH 服务器清单
Get-DnsClientDohServerAddress

# 把内部 DNS 登记为 DoH 服务器(不回退到明文・启用自动升级)
Add-DnsClientDohServerAddress -ServerAddress '10.0.1.2' `
    -DohTemplate 'https://dns.corp.example.com/dns-query' `
    -AllowFallbackToUdp $false -AutoUpgrade $true

也可以用 netsh dnsclient add encryption 登记。全局的 netsh dnsclient set global doh=yes|no|auto 与按服务器的 autoupgrade 是不同的设置。35

全局设置 含义
doh=no 禁止 DoH
doh=yes 按服务器或适配器的设置允许 DoH
doh=auto 自动把发往已知 DoH 服务器的查询强制为 DoH

光有 auto 并不禁止退回明文。失败时是否退回 UDP,由按服务器的 udpfallback(PowerShell 中是 -AllowFallbackToUdp)另行决定。若要只限加密,就把回退也禁用。35

启用了 DDR,还有动态发现的路径

在支持 DDR(Discovery of Designated Resolvers)的版本中,以明文配置的解析器可以通告加密 DNS 的终结点。由于无需登记到静态清单也可能被升级为加密,因此不能断言「不在清单里就不是 DoH」。35

DDR 要生效,需要全局的 netsh dnsclient set global ddr=yes 与按适配器的 set interface <名称> ddr=yes 两者兼备。用 DDR 得到的加密解析失败后是否退回明文由 ddrfallback 决定,默认是禁用。

调查时除了已知清单,还要确认 netsh dnsclient show globalnetsh dnsclient show state,以及对持有 DNS 服务器的适配器用 set interface 设定的值。资料中定义的 showencryptionglobalstate,没有适配器专用的显示子命令。35

把「允许」「要求」与退回明文分开

在设置应用中把 DNS 设置改为手动,只有当首选 DNS 服务器在已知清单中时才能选择「首选 DNS 加密」。选项有下面三个。1

设置应用的选项 行为
仅加密(DNS over HTTPS) 只使用加密
优先加密,也允许未加密的通信 DoH 失败时不作通知地退回明文
仅未加密的通信 以明文发送

组策略「配置 DNS over HTTPS (DoH) 名称解析」有允许、禁止、要求三种。选允许时,除了登记到已知清单,还要满足自动升级、适配器的加密设置、全局 doh=auto 等条件才会使用 DoH。选「要求」时,不支持 DoH 的服务器会导致名称解析本身失败。135

不要在加入域的电脑上应用「要求 DoH」。Microsoft 有明确提醒。因为 Active Directory Domain Services 强烈依赖 DNS,而 Windows Server 自带的 DNS 服务器服务并不支持 DoH 查询。1

抓包时,要把设置与实际通信分开读

实际用 DoH 发出的查询不在 UDP 53,而是进入 443 端口的 TLS。不过即使「允许 DoH」,发往不在已知清单的服务器的查询,以及加密失败后的回退,仍会以明文流出。只是有 DoH 的设置,并不意味着 53 端口的通信就消失了。

看不到 DNS 查询时,除了 hosts、缓存,还要确认 DoH 与 DoT(853 端口)。采集方法请参考数据包捕获文章

6.2 浏览器的 DoH 与操作系统是两回事

Edge 的内置 DNS 客户端,与通过安全 DNS 更改查询目标,分成两段来看会更容易理解。

设置 查询的主体・对象
默认的内置 DNS 客户端 由 Edge 而不是操作系统的 DNS 客户端来查询。所用的 DNS 服务器本身不变
安全 DNS 使用当前提供商 向当前提供商加密查询。失败则以明文重试
安全 DNS 选择别的提供商 向选定的 DoH 解析器查询。失败也不退回明文

内置客户端由 BuiltInDnsClientEnabled 控制,DoH 的查询始终由内置解析器进行。7 安全 DNS 在受组织管理的电脑上默认停用,用 DnsOverHttpsMode(off / automatic / secure)与 DnsOverHttpsTemplates 配置。3637

选了别的提供商的 Edge,可能能查外部站点却查不到只有内部 DNS 才知道的名称。反过来,即使操作系统的 DNS 不正常,也可能只有 Edge 能打开。若维持当前提供商,查询目标并不会改变。

结论是,不要把浏览器的成功与业务应用的成功当作同一条路径的证据。操作系统的路径要用 Resolve-DnsNameping 来确认。

7. 应用走的是哪条路径

在选择调查用的工具之前,先把看的路径对齐。

调用 走的路径 hosts 缓存 NRPT LLMNR/NetBT
getaddrinfo / Dns.GetHostAddresses / HttpClient(直接连接时)1011 操作系统的 DNS 客户端服务。经代理的 HttpClient 只在本地解析代理名称,目标由代理解析 生效 单标签名称时使用(默认与 DNS 并行。失败后的串行仅限停用优化时)
ping 操作系统的 DNS 客户端服务 生效 单标签名称时使用(默认与 DNS 并行。失败后的串行仅限停用优化时)
Resolve-DnsName8 操作系统的 DNS 客户端服务(可用开关选择层) 可用 -NoHostsFile 排除 -CacheOnly 限定 生效 可用 -DnsOnly 排除
nslookup123 直接发往第一台 DNS 服务器 不看 不看 不生效 不使用
Microsoft Edge(默认)76 内置 DNS 客户端(不经过操作系统的 DNS 客户端) 与操作系统的路径不同 与操作系统的缓存不同 不生效(在 Windows DNS API 之外) 与操作系统的路径不同

按调查目的整理 Resolve-DnsName 的主要开关,如下所示。8

想确认的事 开关
仅靠本地缓存能否得到答案 -CacheOnly
想排除 hosts 再试 -NoHostsFile
只用 DNS 协议,不想发出 LLMNR、NetBIOS -DnsOnly
想问特定的 DNS 服务器 -Server
只想试 LLMNR -LlmnrOnly
只想试 LLMNR 或 NetBIOS -LlmnrNetbiosOnly
想允许 DNS 失败时退回 NetBIOS -NetbiosFallback
想选择记录类型 -Type。默认是同时问 A 与 AAAA 的 A_AAAA

7.1 A 与 AAAA,IPv6 先返回

即使名称解析成功,之后的地址选择也可能让连接变慢。

DNS 客户端会同时查询 A(IPv4)与 AAAA(IPv6)。抓包中也能看到两者成对的查询。3 返回答案之后,getaddrinfo 与连接一侧的协议栈会选择要用的地址。Windows Vista 及以后使用 RFC 3484 的前缀表,默认让 IPv6 的全局单播优先于 IPv4。38

不过,仅仅返回了 AAAA,并不意味着一定会尝试 IPv6 连接。在目标选择时,会先排除没有 IPv6 源地址或路由等不可用的目标,再排列候选。39

成为问题的是这种环境:IPv6 的源地址与路由看似存在,实际却不通。名称解析成功了,却在连接上损失时间。IPv6 是否真的被尝试过,不能只看 DNS 响应,还要用连接日志或抓包确认。

Microsoft 不推荐用停用 IPv6 来应对,因为 Windows 的一部分组件会无法工作。取而代之,它介绍的方法是把 DisabledComponents 设为 0x20,在前缀策略中让 IPv4 优先。38 localhost 被解析为 ::1、与假定 127.0.0.1 的调查产生冲突的例子,数据包捕获文章中也有讲。

8. 排查步骤 ── 从上往下逐层剥离

在连不上的电脑上,按下面的顺序执行。各条命令都是为了限定路径,仅仅成功并不能证明平时的解析路径也是如此。要结合结果的比较和最后的抓包。

步骤 要确认的事
1 应用交过来的名称的形态
2 缓存与 hosts 的答案
3 排除 hosts、LLMNR、NetBIOS 后的 DNS 结果
4 实际解析路径上按 DNS 服务器分别的结果
5 单标签名称用 LLMNR、NetBT 的解析
6 能连与不能连的电脑之间的设置差分
7 有没有发出数据包,返回了什么

步骤 1: 确认名称的形态

在日志或配置文件中确认应用实际交过来的名称。是单标签名称、以 .local 结尾、还是末尾带点,路径都会不同。像 http://app01/ 这样的短名称,就要从 4.1 节的补全和 5.4 节各台电脑的差别查起。

步骤 2: 仅靠缓存与 hosts 能否解析

Resolve-DnsName -Name 'app01.corp.example.com' -CacheOnly
Get-DnsClientCache -Entry 'app01.corp.example.com'
Get-Content "$env:SystemRoot\System32\drivers\etc\hosts" | Select-String -Pattern 'app01'
结果 怎么读与下一步确认
出了正确的答案 这次在到达 DNS 服务器之前答案就定了
出了旧的、错误的答案 若来自 hosts 就改那一行。若来自缓存,就在清除后按步骤 3 确认重新取得的答案
「Name does not exist」 否定缓存。Clear-DnsClientCache 之后进入步骤 3
没有答案 有可能是普通的缓存未命中。进入步骤 3

-CacheOnly 只是把这次查找限定在本地缓存。若错误的答案本来就是从 DNS 服务器学来的,清除后同样的值还会回来。在缓存中存在,并不能证明 DNS 服务器与此无关。8

步骤 3: 仅用 DNS 能否解析

# 排除 hosts,不发出 LLMNR/NetBIOS,只用已配置的 DNS 服务器查询
Resolve-DnsName -Name 'app01.corp.example.com' -NoHostsFile -DnsOnly

如果步骤 2 没有答案而这里成功了,多半只是普通的缓存未命中。能说是缓存或 hosts 的问题的,是步骤 2 中出现了旧答案、错误答案或否定缓存的情况。

如果这里也失败,就要查通往 DNS 服务器的路径、服务器一侧以及客户端一侧的策略。进入步骤 4 之前,请确认下面这些。

  • Get-DnsClientNrptPolicy -Effective: 有没有把查询指向别的 DNS 服务器的规则。
  • Get-DnsClientDohServerAddress 与 DoH 的组策略: 有没有对不支持的服务器「要求 DoH」。

若有 NRPT,步骤 4 的目标服务器就会变。如果原因是「要求 DoH」,那么路径和服务器都健全,唯独名称解析失败。请先完成 4.4 节、6.1 节的确认。

步骤 4: 逐台服务器直接查询

收集正在连接的适配器的 DNS 服务器;若目标名称上有 NRPT 生效,就换成该规则的服务器。只用 IPv6 配置的 DNS 服务器也要纳入对象。

$name = 'app01.corp.example.com'
# 从 IPv4 与 IPv6 两侧收集正在连接的接口的 DNS 服务器。
# 已断开的 VPN 或虚拟交换机上残留设置的服务器与当前的解析路径无关,所以排除(只用 IPv6 配置的服务器不要漏掉)
$connected = @((Get-NetIPInterface -ConnectionState Connected).ifIndex | Select-Object -Unique)
$servers = @((Get-DnsClientServerAddress |
    Where-Object { $_.ServerAddresses -and ($connected -contains $_.InterfaceIndex) }).ServerAddresses)
# 对这个名称生效的 NRPT 规则的服务器(Always On VPN 或 DirectAccess 写入的那些)不会出现在适配器的设置里,所以从实效策略中选取。
# Get-DnsClientNrptPolicy 的 -Namespace 只按规则的 Namespace 属性筛选,不做与名称的匹配判定。
# 因此要自行比对 Any 规则(.)、后缀规则(以点开头。对命名空间本身及其子域生效)、FQDN 规则、前缀规则(主机名部分,也可以是 web* 这样的通配符),
# 并采用更具体(更长)的规则。Any 规则最短,所以只有在没有其他匹配规则时才会被选中
# Namespace 是字符串的集合(显示为 Namespace : {.corp.example.com} 这样),所以要按规则展开元素来比对,并按匹配到的命名空间长度排序
# 末尾带点的绝对名称(app01.corp.example.com.)只在比对时去掉点。传给 Resolve-DnsName 的仍是原始的 $name
$matchName = $name.TrimEnd('.')
$label = $matchName.Split('.')[0]
$matched = foreach ($policy in @(Get-DnsClientNrptPolicy -Effective)) {
    foreach ($ns in @($policy.Namespace)) {
        if (-not $ns) { continue }
        $hit = if ($ns -eq '.') { $true }
               elseif ($ns.StartsWith('.')) { $matchName.Equals($ns.TrimStart('.'), [System.StringComparison]::OrdinalIgnoreCase) -or $matchName.EndsWith($ns, [System.StringComparison]::OrdinalIgnoreCase) }
               elseif ($ns.Contains('.')) { $matchName.Equals($ns, [System.StringComparison]::OrdinalIgnoreCase) }
               else { $label -like $ns }
        if ($hit) { [pscustomobject]@{ Namespace = $ns; Policy = $policy } }
    }
}
$rule = $matched | Sort-Object { $_.Namespace.Length } -Descending | Select-Object -First 1
$policyServers = @()
if ($rule) { $policyServers = @(@($rule.Policy.NameServers) + @($rule.Policy.DirectAccessDnsServers) | Where-Object { $_ }) }
if ($policyServers.Count -gt 0) {
    # 如果 NRPT 为这个命名空间指定了服务器,那么步骤 3 的查询就是发往那台服务器。适配器的服务器在路径之外,所以替换掉
    $servers = $policyServers
}
$servers = $servers | Where-Object { $_ } | Select-Object -Unique
foreach ($server in $servers) {
    $sw = [System.Diagnostics.Stopwatch]::StartNew()
    try {
        $r = Resolve-DnsName -Name $name -Server $server -DnsOnly -ErrorAction Stop
        $status = 'OK'
        # 多条记录的排列会随响应变化,所以排序后再比较
        $answer = ($r.IPAddress | Sort-Object) -join ','
    } catch {
        # 否定响应(没有这个名称)、SERVFAIL、超时都会走到这里。不要丢掉原因,保留下来
        $status = $_.Exception.Message
        $answer = ''
    }
    [pscustomobject]@{ Server = $server; Status = $status; Answer = $answer; Milliseconds = [int]$sw.ElapsedMilliseconds }
}

首先,把要比较的服务器对齐

NRPT 的 NameServersDirectAccessDnsServers 有时不会出现在适配器的 DNS 设置中。如果步骤 3 问的是 NRPT 的服务器,而步骤 4 只查适配器的服务器,那就比较了不同的路径。

NRPT 有后缀、FQDN、前缀、Any(.)等规则,更具体的规则优先。40 -Namespace 只按规则的属性筛选,不做与主机名的匹配判定。因此上面的代码展开规则的命名空间,与目标名称做比对。23

在分离 DNS 的 VPN 中,家里一侧的解析器对内部名称返回否定响应、只有 NRPT 一侧返回肯定响应,这是正常的。若要把路径之外的服务器也拿来比较,就作为「对照」单独记录,不要混进区域是否一致的判定里。对已断开适配器上残留服务器的超时,也与当前解析路径的延迟无关。

接着,分辨结果

结果 要查的东西
只有特定服务器超时 那台服务器变成无响应的原因
「名称不存在」等否定响应 与超时区分开,确认名称与区域的内容
响应的 IP 地址不同 确认它们是不是同一角色的服务器,并按记录集合比较
只是记录的顺序不同 可能是轮询。若排序后的集合相同,就不要仅凭顺序判定区域不一致

若集合也不同,就确认区域的内容与序列号。另外,这里是用 -Server 固定了目标的测量。4.2 节所说的「到第 4 位为止要 4 秒」这种由列表位置带来的延迟,要在步骤 3 或它的抓包中确认。

步骤 5: 确认链路本地这一层

Resolve-DnsName -Name 'app01' -LlmnrOnly          # 只用 LLMNR
Resolve-DnsName -Name 'app01' -LlmnrNetbiosOnly   # 只用 LLMNR 或 NetBIOS(不使用 DNS)
nbtstat -c                                        # NetBIOS 名称缓存

这项确认针对的是单标签名称。-NetbiosFallback 只在 DNS 失败时才退回 NetBIOS,因此对能用 DNS 解析的名称来说,它并不能确认 NetBIOS。8

结果按下面的方式读。

结果 能知道的/仍然不知道的
-LlmnrOnly 成功 能用 LLMNR 解析。不过平时是否也采用了那个答案并不一定
-LlmnrOnly 失败而 -LlmnrNetbiosOnly 成功 不能断定是 NetBIOS 回答的。也可能是因为丢包或对方的启动时机,在后一次尝试中由 LLMNR 回答了
能连的电脑只有这一层成功,连不上的电脑失败 怀疑对单标签名称路径的依赖。根本对策是 FQDN 化与 DNS 登记

到底是哪个协议回答的,要在抓包中通过 UDP 5355(LLMNR)与 UDP 137(NetBT)来分辨。要确认平时的解析路径,还要与不带开关的 Resolve-DnsName 返回的地址比较;若不一致,就用抓包确认被采用的响应。因为默认情况下 DNS 也在并行查询。

步骤 6: 取设置转储的差分

在「只有部分电脑」的调查中,要在能连和不能连的电脑上执行同一个脚本再比较。

# name-resolution-dump.ps1 -- 以管理员权限执行,把两台的输出文件并排比较
$out = "$env:COMPUTERNAME-name-resolution.txt"
$sections = [ordered]@{
    'Get-DnsClientServerAddress' = { Get-DnsClientServerAddress | Format-Table -AutoSize | Out-String -Width 200 }
    'Get-DnsClientGlobalSetting' = { Get-DnsClientGlobalSetting | Format-List | Out-String }
    'Get-DnsClient'              = { Get-DnsClient | Format-Table InterfaceAlias, ConnectionSpecificSuffix, UseSuffixWhenRegistering -AutoSize | Out-String -Width 200 }
    'Get-DnsClientNrptPolicy'    = { Get-DnsClientNrptPolicy -Effective | Format-List | Out-String }
    'Get-DnsClientDohServerAddress' = { Get-DnsClientDohServerAddress | Format-Table -AutoSize | Out-String -Width 200 }
    'netsh dnsclient show state' = { netsh dnsclient show state 2>&1 | Out-String }
    'Get-NetIPInterface'         = { Get-NetIPInterface | Sort-Object AddressFamily, InterfaceMetric | Format-Table InterfaceAlias, AddressFamily, InterfaceMetric, ConnectionState, Dhcp -AutoSize | Out-String -Width 200 }
    'DNSClient policy registry'  = { Get-ItemProperty 'HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\DNSClient' -ErrorAction SilentlyContinue | Format-List | Out-String }
    'ipconfig /all'              = { ipconfig /all | Out-String }
}
$sections.GetEnumerator() | ForEach-Object {
    "===== $($_.Key) ====="
    try { & $_.Value } catch { "ERROR: $($_.Exception.Message)" }  # 不存在的项目(如 Windows 10 的 DoH)作为错误保留下来
} | Set-Content -Path $out -Encoding UTF8
Write-Host "wrote $out"

要比较的是 DNS 服务器的排列、搜索列表、连接特定后缀、NRPT、DoH、接口跃点数、策略值。

HKLM\SOFTWARE\Policies\Microsoft\Windows NT\DNSClient 中有「关闭多播名称解析」的 EnableMulticast、「关闭智能多宿主名称解析」的 DisableSmartNameResolution,以及搜索列表和主后缀等。4 把差分与前面梳理过的各层作用对照着看。

步骤 7: 用数据包捕获取得佐证

Microsoft 的数据收集步骤是:在客户端和服务器两侧启动 netsh trace start capture=yes,用 ipconfig /flushdns 丢掉缓存后重现问题,再用 netsh trace stop 停止。41

在 Wireshark 中用 dns.qry.name == "app01.corp.example.com"dns.qry.name contains "app01" 筛选,确认向哪台服务器问了什么、返回了什么。

抓包中看到的 要查的位置
没有发出查询 除了缓存、hosts,以及 DoH、DoT 或链路本地等其他路径,还要确认发送侧防火墙是否阻断了 UDP 53
发出了查询但没有响应 通往 DNS 服务器的路径、防火墙、服务器无响应
返回了否定响应 查询的名称与服务器一侧的记录
返回了肯定响应 名称解析之后的连接一侧。也确认所用的地址与 IPv6

当发送侧防火墙阻断了 UDP 53 时,Resolve-DnsName 会超时,抓包中也不会出现 DNS 查询。不仅要区分「名称解析成功但通信没出去」,也要区分「失败且通信没出去」。3

DNS 之外,LLMNR 看 5355,mDNS 看 UDP 5353,NetBT 的名称服务看 UDP 137。DoH 是 443,DoT 是 853。抓包的采集与读法汇总在数据包捕获文章中。

9. 业务应用一侧的设计 ── 让它扛得住名称解析问题

要让调查变轻松,应用一侧能留下「用什么名称、解析成了什么、在哪里失败」是很关键的。把应用的日志与 IT 部门采集的设置转储、抓包对上,就更容易决定从第 8 章的哪一步查起。

目标用 FQDN 保存,不依赖 hosts

配置文件的默认值、快捷方式、UNC 路径都改成 FQDN,以摆脱单标签名称的后缀补全以及对 LLMNR、NetBT 的依赖。不过 5.4 节提到需要注意的地方仍在:.local 名称会并用 mDNS,末尾没有点的名称会受附加后缀策略的影响。

hosts 对开发过程中的临时覆盖很方便,但需要管理员权限和手工操作,既不好分发也不好管理变更历史,而且有的解析器根本不看它(nslookup 就不看12)。目标的切换应当在配置文件中进行。

记录名称解析的结果、耗时与失败原因

在启动时等时机,记录主要目标的 IPv4、IPv6 地址与耗时。Dns.GetHostAddresses 返回的结果与 getaddrinfo 相同,因此可以追溯「哪台电脑、从什么时候起、解析成了什么」。11

// 启动时记录主要目标的名称解析结果(.NET 6 及以上)
static async Task LogNameResolutionAsync(ILogger logger, string host)
{
    var sw = System.Diagnostics.Stopwatch.StartNew();
    try
    {
        var addresses = await System.Net.Dns.GetHostAddressesAsync(host);
        logger.LogInformation("名称解析 {Host} -> {Addresses} ({Elapsed} ms)",
            host, string.Join(",", addresses.Select(a => a.ToString())), sw.ElapsedMilliseconds);
    }
    catch (System.Net.Sockets.SocketException ex)
    {
        logger.LogError(ex, "名称解析失败 {Host} 错误 {Code} ({Elapsed} ms)",
            host, ex.SocketErrorCode, sw.ElapsedMilliseconds);
        throw;
    }
}

失败要记进日志并重新抛出。因为若悄悄换成别的名称或固定 IP,调查时就看不出实际的路径了。有了错误码与耗时,IT 部门就能判断该从步骤 2~4 的哪一步开始。

把超时与 IPv6 的答案考虑进去

DNS 客户端对无响应的服务器,每个查询候选最多要用 10 秒。21 若后缀搜索使候选变成多个,整体就可能超过 10 秒。

把连接超时压到 2~3 秒后,在能回答的服务器排在第 4 位及以后的配置里,名称解析就赶不上期限。不过因为第 2 台是在 1 秒后、第 3 台是在 2 秒后被查询,所以只掉一台并不一定就会失败。要结合 4.2 节的重传时间来设计。

另外,如果返回了 AAAA,并且存在 IPv6 的源地址与路由,Windows 默认会让 IPv6 优先。38 只考虑 IPv4 的连接代码,可能出现名称解析成功却连接失败的情况。要把名称解析的成功与连接的成功分开,并让代码能处理两种地址。

10. 总结

Windows 的名称解析首先要分清的是名称的形态、给出答案的层、以及应用走的路径

缓存与 hosts 先回答,对单标签名称则默认由 DNS 与 LLMNR、NetBT 并行工作。.local 还会加上 mDNS。进入 DNS 之后,后缀、重传时间、多网卡、NRPT 都会改变结果。DoH 是替换其传输通道的功能,要与浏览器的内置解析器分开考虑。

调查按 -CacheOnly-NoHostsFile -DnsOnly-Server-LlmnrOnly 的顺序限定路径,再用设置转储的差分与抓包来确认。重要的是不要漏掉否定缓存、无响应与否定响应的区别,以及客户端一侧的策略。

遇到「只有这台电脑连不上」时,请先确认下面两点。

那个名称是以什么形态被交过来的?在那台电脑上,是哪条路径在回答?

把这两点对齐,就能缩小要查的范围。

相关文章

相关的咨询领域

小村软件有限公司承接「只有部分电脑的业务应用连不上内部服务器」「浏览器能打开、应用却名称解析失败」这类由名称解析引发的通信故障的原因调查,业务应用能否承受停用 LLMNR、DoH、VPN 等环境变更的设计评审,以及记录名称解析结果与超时的通信层实现。如果能附上能连与不能连的电脑的设置转储再来咨询,调查的切入点会更快确定。

参考链接

  1. Microsoft Learn, Secure DNS Client over HTTPS (DoH). 关于只有首选/备用 DNS 服务器在已知 DoH 服务器清单中时才能配置 DoH、设置应用的三个加密选项以及「优先加密」会不作通知地退回明文、组策略「配置 DNS over HTTPS (DoH) 名称解析」的 Allow/Prohibit/Require、不得在加入域的电脑上启用 Require 的理由、已知服务器清单(Cloudflare・Google・Quad9)与 Get-DnsClientDohServerAddress、用 Add-DnsClientDohServerAddress 添加,以及与 NRPT 的并用。  2 3 4 5

  2. Microsoft Learn, MSFT_DNSClientGlobalSetting class. 关于作为 DnsClient cmdlet 基础的 WMI 类,其最低支持的操作系统是 Windows 8 / Windows Server 2012。 

  3. Microsoft Learn, Troubleshoot DNS client name resolution issues. 关于 DNS 客户端按缓存→hosts 文件→DNS 服务器的顺序解析、hosts 中有对应项时不会有 DNS 通信、堵住 UDP 53 会让 Resolve-DnsName 超时、多台服务器中可达的少时约需 4 秒、nslookup 只问第一台 DNS 服务器、长后缀搜索列表带来的延迟、用末尾的点做特定查询、以及用 Measure-Command 测量耗时。  2 3 4 5 6 7 8 9

  4. Microsoft Learn, Policy CSP - ADMX_DnsClient. 关于「关闭智能多宿主名称解析」(默认把 DNS・LLMNR・NetBT 并行发往所有网络,多个肯定响应按绑定顺序采用;启用后变为 DNS→LLMNR→NetBT 的串行)、「关闭智能协议重新排序」(默认在非域网络上单标签名称优先采用链路本地响应)、「关闭多播名称解析」(LLMNR 是次要协议且会在所有适配器上被停用,注册表值 EnableMulticast)、DNS 后缀搜索列表与降级、「允许对多标签的非限定名称查询附加 DNS 后缀」(对含点但末尾无点的名称也附加后缀查询的策略)、主 DNS 后缀、连接特定后缀,以及注册表项 Software\Policies\Microsoft\Windows NT\DNSClient。  2 3 4 5 6 7 8 9

  5. Microsoft Learn, DNS queries and lookups. 关于 hosts 的内容在 DNS 客户端服务启动时读入缓存、DNS 响应也在 TTL 期间保存于缓存、FQDN 与多标签名称与单标签名称的查询构造方式不同且会依次使用后缀搜索列表・主后缀・降级・连接特定后缀、肯定与否定响应都会被缓存、多适配器下的查询顺序与因否定响应而排除适配器、自适应超时与无响应服务器的缓存。  2 3 4 5 6 7 8 9 10

  6. Microsoft Learn, VPNv2 CSP. 关于 VPN 配置文件的 DomainNameInformationList 就是 NRPT 的规则、只有使用 Windows DNS API 的应用才能用到 NRPT 而自带 DNS 实现的应用会绕过、其例子是 nslookup,以及确认 NRPT 时务必使用 Resolve-DnsName。  2 3 4

  7. Microsoft Learn, Microsoft Edge policy: BuiltInDnsClientEnabled. 关于 Edge 默认使用内置 DNS 客户端、该策略不影响使用哪台 DNS 服务器,以及 DoH 的查询始终由内置解析器进行。  2 3 4

  8. Microsoft Learn, Resolve-DnsName. 关于 -CacheOnly(仅本地缓存)、-DnsOnly(仅 DNS 协议,不发出 LLMNR・NetBIOS)、-NoHostsFile(跳过 hosts)、-LlmnrOnly、-LlmnrNetbiosOnly、-LlmnrFallback、-NetbiosFallback、-Server、-Type(默认 A_AAAA)、-QuickTimeout、-TcpOnly 各参数。  2 3 4 5 6

  9. Microsoft Learn, Windows security book: Network security. 关于 Windows 11 的 DNS 客户端支持 DoH 与 DoT、可通过组策略与程序配置 DoH,以及加密 DNS 的支持与 NRPT・系统的 hosts 文件・按适配器或按配置文件的解析器指定等既有 DNS 配置整合在一起。  2 3

  10. Microsoft Learn, getaddrinfo function (ws2tcpip.h). 关于针对 NS_DNS 命名空间用 DNS・本地 hosts 文件・其他机制把名称转换成地址、汇总多个命名空间提供程序的响应,以及 Unicode 版是 GetAddrInfoW。  2

  11. Microsoft Learn, Dns.GetHostAddresses Method. 关于它由底层操作系统的名称解析 API(Windows 上是 getaddrinfo)实现,以及写在 hosts 文件中的主机不会去问 DNS 服务器而直接返回那个地址。  2 3

  12. Microsoft Learn, Troubleshoot Azure DNS. 关于 nslookup 不使用操作系统的本地 DNS 解析器库,绕过本地 DNS 缓存・hosts 文件・NRPT,以及这些层相关时应使用 Resolve-DnsName。  2 3

  13. Microsoft Learn, ipconfig. 关于 /displaydns 显示包含从 hosts 读入的条目与最近解析的记录在内的 DNS 客户端解析器缓存、/flushdns 丢弃包含否定缓存条目在内的缓存、以及 /registerdns 的动态注册。  2

  14. Microsoft Learn, Troubleshooting DNS clients. 关于 ipconfig /displaydns 中失败的名称显示「Name does not exist」即表示 DNS 服务器的否定响应被缓存在客户端、用 ipconfig /flushdns 解决、以及 nslookup 不使用客户端的 DNS 缓存。 

  15. Microsoft Learn, Windows Firewall profile doesn’t always switch to Domain when you use a third-party VPN client. 关于 Dnscache\Parameters 的 MaxNegativeCacheTtl 默认值为 5 秒,设为 0 可停用否定缓存。 

  16. Microsoft Learn, Clear-DnsClientCache. 关于删除 DNS 客户端缓存的全部内容,等同于 ipconfig /flushdns。 

  17. Microsoft Learn, Get-DnsClientCache. 关于取得本地 DNS 客户端缓存的内容,并可按 Name・Type・TimeToLive・Section 等筛选。 

  18. Microsoft Learn, How to configure a domain suffix search list on the Domain Name System clients. 关于一旦配置了域后缀搜索列表就只使用该列表,主 DNS 后缀、连接特定后缀与降级都不再使用。 

  19. Microsoft Learn, Get-DnsClientGlobalSetting. 关于取得不与接口绑定的 DNS 客户端全局设置(UseSuffixSearchList・SuffixSearchList・UseDevolution・DevolutionLevel)。 

  20. Microsoft Learn, Get-DnsClient. 关于取得按接口的 ConnectionSpecificSuffix・RegisterThisConnectionsAddress・UseSuffixWhenRegistering。 

  21. Microsoft Learn, DNS client resolution timeouts. 关于 DNS 服务器为 1 台、2 台、3 台及以上时的重传时机(开始后 1・2・4・8 秒重传,10 秒放弃)、收到否定响应就停止而只有无响应时才尝试下一台、以及第 4 位及以后的服务器最少要 4 秒之后才被问到。  2 3 4

  22. Microsoft Learn, Automatic interface metric. 关于现今 Windows 中接口的优先顺序由接口跃点数决定,可用 Get-NetIPInterface 查看与更改跃点数。 

  23. Microsoft Learn, Get-DnsClientNrptPolicy. 关于取得 NRPT 中按命名空间配置的设置(DNS 客户端的名称服务器、DirectAccess、DNSSEC 等),用 -Effective 显示实效策略、用 -Namespace 显示特定命名空间的部分。  2

  24. IETF, RFC 6762: Multicast DNS. 关于 mDNS 是以 UDP 端口 5353 的组播在同一链路内解析 .local 名称的协议。  2 3

  25. Microsoft Learn, Microsoft Security Bulletin MS11-030. 关于 LLMNR 使用 TCP/UDP 5355、作为规避措施在防火墙上阻断 5355 与启用组策略「关闭多播名称解析」,以及其影响是计算机可能不再被其他计算机看到。  2

  26. IETF, RFC 4795: Link-Local Multicast Name Resolution (LLMNR). 关于 LLMNR 的查询以 UDP 组播(端口 5355)发送,TCP 用于被截断的响应等单播交互。 

  27. Microsoft Tech Community, Networking Blog, Aligning on mDNS: ramping down NetBIOS name resolution and LLMNR. 关于 Microsoft 于 2022 年 4 月公布的、向 mDNS 靠拢并逐步收缩 NetBIOS 名称解析与 LLMNR 的方针。  2

  28. Microsoft Learn, How to configure TCP/IP networking while NetBIOS is turned off. 关于 NetBIOS 名称服务使用 UDP 137、数据报服务使用 UDP 138、会话服务使用 TCP 139,以及停用 NetBT 后就不再监听这些端口。 

  29. Microsoft Learn, Windows security baseline (Azure Policy guest configuration). 关于 NetBT 的节点类型(B-node 仅广播、P-node 仅 WINS、M-node 先广播后 WINS、H-node 先 WINS 后广播)、未配置 WINS 时默认 B-node 而已配置时默认 H-node,以及推荐 P-node。  2 3

  30. Microsoft Learn, Windows Internet Name Service (WINS). 关于 WINS 是把 NetBIOS 名称对应到 IP 地址的遗留服务,推荐不再新建部署而使用 DNS,已部署的则迁移到 DNS 后废止。  2

  31. Microsoft Learn, nbtstat. 关于 /c 显示 NetBIOS 名称缓存、/R 清除缓存并重新读入 Lmhosts 中预标记的条目、/RR 释放并重新向 WINS 注册。 

  32. Microsoft Learn, Features removed or no longer developed in Windows Server. 关于 Computer Browser 服务作为过时且不安全的设备发现协议被弃用,以及 WINS 等遗留名称解析相关功能的处置。 

  33. Microsoft Learn, Direct host SMB over TCP/IP. 关于 Windows Vista / Windows Server 2008 及以后的 SMB 2.0.2 需要 TCP 445 且不使用 NetBIOS 会话传输。该资料把可以把名称解析标准化到 DNS 列为其优点,但那说的是 SMB 的传输通道,并不会阻止客户端的 DNS 客户端用 LLMNR 或 NetBT 解析单标签名称(正文 5.4 节)。 

  34. Microsoft Learn, Add-DnsClientDohServerAddress. 关于把 DoH 服务器配置添加到已知服务器清单,并用 -DohTemplate・-AllowFallbackToUdp・-AutoUpgrade 指定加密失败时的回退与自动升级。 

  35. Microsoft Learn, netsh dnsclient. 关于用 add/set encryption 登记 DoH・DoT 服务器(dohtemplate・dothost・autoupgrade・udpfallback)、用 set global 做 doh/dot/ddr 的全局设置,以及 show encryption・show global・show state。  2 3 4 5

  36. Microsoft Learn, User data and privacy in Microsoft Edge: Secure DNS. 关于安全 DNS 默认使用当前提供商、加密连接失败时以明文重试、选择特定提供商则不退回明文,以及在受组织管理的电脑上默认停用。 

  37. Microsoft Learn, Microsoft Edge policy: DnsOverHttpsMode. 关于 off・automatic・secure 三种模式,以及在受管理设备上未配置时不发送 DoH 查询。 

  38. Microsoft Learn, Guidance for configuring IPv6 in Windows for advanced users. 关于 Windows Vista 及以后用 RFC 3484 的前缀表决定使用哪个地址、默认让 IPv6 全局单播优先于 IPv4,以及不推荐停用 IPv6 而应使用 DisabledComponents 的 0x20 来「优先 IPv4」。  2 3

  39. IETF, RFC 3484: Default Address Selection for Internet Protocol version 6 (IPv6). 关于目标地址选择规则的第 1 条是「避开不可用的目标」,先排除没有源地址或路由的目标,再按前缀策略的优先级排列候选。 

  40. Microsoft Learn, Configure DNSSEC rules using the Name Resolution Policy Table. 关于 NRPT 的命名空间种类(后缀・前缀・FQDN・子网・Any)、后缀是包含子域的末尾匹配,以及更具体的规则优先于更一般的规则。 

  41. Microsoft Learn, Troubleshooting Domain Name System (DNS) issues: Data collection. 关于在客户端与服务器上启动 netsh trace start capture=yes、用 ipconfig /flushdns 丢掉缓存后重现、再用 netsh trace stop 停止的数据收集步骤。 

共享相同标签的最新文章。可以围绕相近的主题进一步加深理解。

与本文相近的主题页面。以本文为起点,可以进一步了解相关服务和其他文章。

本文与以下服务页面相关联,欢迎从最接近的入口查看。

常见问题

汇总了咨询这一主题时常见的问题。

我改了 hosts 文件却不生效,为什么?
Windows 的 hosts 文件内容会在 DNS 客户端服务启动时读入缓存,名称解析按缓存→hosts→DNS 服务器的顺序推进。不生效时,先用 ipconfig /displaydns 查看该名称的条目,如果还留着旧的响应,就用 ipconfig /flushdns 丢掉它。接着要怀疑你所用的工具是否走了 Windows 的解析器。nslookup 不使用操作系统的解析器,它会绕过缓存、hosts 和 NRPT 直接向 DNS 服务器查询,因此 hosts 的内容完全不会反映出来。要看包含 hosts 在内的实际解析结果,请用 Resolve-DnsName 或 ping。如果仍然不生效,就确认这个应用是否像浏览器那样自带解析器或 DoH。
浏览器里网站能打开,可是只有业务应用名称解析失败。
这多半是浏览器和应用走了不同的路径去查名称。Microsoft Edge 默认不用操作系统的 DNS 客户端,而是用内置的 DNS 客户端与 DNS 服务器通信;如果在安全 DNS(DoH)中选了别的提供商,它就会向外部解析器查询。另一方面,.NET 的 Dns.GetHostAddresses 以及直接连接目标的 HttpClient 会走操作系统的 getaddrinfo,因此会完整受到 hosts、DNS 缓存、NRPT 与后缀搜索列表的影响(经 HTTP 代理的请求中,目标的名称由代理一侧解析)。当两者给出不同答案时,用 Resolve-DnsName 和数据包捕获把「哪条路径向哪台 DNS 服务器问了什么」对上,是最快的办法。
设置应该是一样的,却只有部分电脑连不上内部服务器。该比较什么?
比较名称的形态,以及那台电脑是在哪一层得到答案的。单标签名称(像 server01 这样不含点的名称)会被电脑的 DNS 后缀搜索列表或连接特定后缀补全后送往 DNS,并且默认还会并行地向 LLMNR、NetBIOS 广播这类仅限同一子网的手段查询(只有在停用了优化之后,才会在 DNS 失败后依次尝试。如果配置了 WINS,NetBIOS 可以用单播跨越子网)。加入域的电脑可能因为后缀补全成 FQDN 而解析成功,但经 VPN 或位于其他子网的电脑,以及停用了 LLMNR 与 NetBIOS 的电脑,同一个名称就解析不了。可靠的做法是在能连和不能连的两台电脑上都采集 Get-DnsClientServerAddress、Get-DnsClientGlobalSetting、Get-DnsClient、Get-DnsClientNrptPolicy -Effective 的输出并做差分。根本对策是把配置文件和快捷方式里的目标改成 FQDN。
名称解析不是失败,而是等了几秒才终于连上。原因是什么?
这是 DNS 客户端的超时与重试机制显现了出来。对于没有响应的 DNS 服务器,Windows 会在开始后的 1 秒、2 秒、4 秒、8 秒时重传,10 秒时放弃。即使配置了多台 DNS 服务器,只要能响应的那台排在列表第 4 位及以后,就至少要等 4 秒才会去问它。另外,很长的 DNS 后缀搜索列表也会因为解析单标签名称时逐个尝试后缀而累积延迟。用 Measure-Command 测量 Resolve-DnsName 的耗时,并在 Wireshark 中用 dns.qry.name 过滤,看看是对哪台服务器的查询没有得到响应。
出于安全考虑停用了 LLMNR 与 NetBIOS,结果有些设备按名称连不上了。
这是可以预期的副作用。LLMNR 与 NetBIOS over TCP/IP 是在同一子网内解析未登记到 DNS 的设备的单标签名称的次要手段,停用它们就等于去掉了那条路径。Microsoft 自己也在 2022 年提出了向 mDNS 靠拢、逐步收缩 NetBIOS 名称解析与 LLMNR 的方针,所以停用这个方向本身是正确的判断。对策是把名称解析集中到 DNS:在内部 DNS 中登记设备的 A 记录,或者启用通过 DHCP 的动态注册,并把应用和共享的目标改写成 FQDN。支持 mDNS 的设备可以用 .local 名称解析,但这条路径同样只限于组播能到达的范围。
在 Windows 11 上启用 DoH(DNS over HTTPS)后,内部的名称解析会怎样?
DoH 是把 DNS 客户端向已配置的 DNS 服务器查询时的传输通道换成 HTTPS 的功能,hosts、缓存、NRPT 这些既有顺序照旧有效。如果没有启用 DDR(Discovery of Designated Resolvers),能用 DoH 的只有列在已知 DoH 服务器清单中的服务器;要用内部 DNS,就需要管理员用 Add-DnsClientDohServerAddress 登记。若把组策略「配置 DNS over HTTPS (DoH) 名称解析」设为「要求 DoH」,那么在不支持 DoH 的服务器上名称解析本身就会失败。Microsoft 明确写明不要在加入域的电脑上启用这项设置,因为 Active Directory 依赖的 Windows Server 自带 DNS 服务器服务并不支持 DoH 查询。

作者简介

本文作者的个人简介页面。

Go Komura

小村软件有限公司 代表

以 Windows 软件开发、技术咨询与故障排查为中心,擅长难以复现的故障调查,以及既有资产仍在运行的项目。

返回博客列表