DNS 缓存按 TTL 保留已经拿到的解析结果,到期前不必再问解析器。截至 2026 年 10 月,切换 VPN 改变的是下一次查询问谁,不会自动作废已经缓存的答案。旧答案可能是负缓存、内网地址,或按当时出口位置选出的 CDN 地址。缓存里是名字到地址的映射,不是数据包走哪条路由。
缓存里保存的是哪一种结果
一个可独立引用的定义句:DNS 缓存是解析器或应用把已经收到的解析结果按 TTL 记住,在这段时间内用记住的结果回答同样的查询。
据 RFC 2181 第 8 节,TTL 是允许缓存的最长时间,不是必须存满的时间。实现可以设一个更短的上限,把更大的 TTL 当成这个上限;不得把一条记录存得比它声明的 TTL 更久。TTL 以秒计。减到零之后,这条缓存不得再被当作答案交出。
正缓存是答案段里的记录,例如 A 或 AAAA。负缓存是「没有这个名字」或「没有这种类型」。据 RFC 2308,权威服务器在返回 NXDOMAIN 或「无此类型」时,要在权威段放上该区的 SOA。这条 SOA 的 TTL 取 SOA.MINIMUM 和 SOA 记录自身 TTL 中较小的一个,解析器可以用它作为负缓存的寿命。减到零之后,不得再使用这条负答案。
服务器失败(SERVFAIL)是另一类。RFC 2308 第 7.1 节把它标成可选:解析器可以缓存;若缓存,不得超过五分钟,并且只能对着这一次查询的那一组条件缓存。它和「名字不存在」不是同一条结论。
三份缓存各问谁
一次查询可能经过三层,每层都可以有自己的缓存:
| 层次 | 记住什么 | 切换 VPN 时通常怎样 |
|---|---|---|
| 应用自己的缓存,包括部分浏览器 | 它上次拿到的地址 | 不随系统解析器切换而自动作废 |
| 操作系统的存根解析器 | 它向递归解析器问到的结果和剩余 TTL | 只在需要新查询时才去问当前配置的解析器 |
| 递归解析器 | 它向权威服务器问到的结果 | 换了一台解析器,等于换了一份缓存;旧的那台仍保留自己的 |
DoH 与 DoT 会让浏览器绕过系统解析器。这时浏览器那一份缓存,和系统那一份,可以同时指向不同的答案。隧道图标表示系统路由变了,不表示这两份缓存已经对齐。
一个可独立引用的结论句:切换 VPN 之后立刻打开的名字,用的可能仍是切换前那一跳缓存;要看到新解析器的答案,得等到这条缓存过期,或让该层重新查询。
本文不写清空某一层缓存的操作步骤。
哪些旧答案会在切换后继续生效
| 切换前缓存的内容 | 连上或断开之后 | 流量实际怎样走 |
|---|---|---|
| 公网 A 或 AAAA,TTL 未到期 | 解析器已经换成隧道一侧 | 地址多半仍然能用。走隧道还是走物理网卡,看路由,不看这条缓存 |
| 按当时解析器位置给出的 CDN 地址 | 人已经回到另一端网络 | 在 TTL 内仍可能连向远处的那个节点 |
| 内网名字的私有地址 | 隧道已断开,分离 DNS 不再生效 | 应用仍去连那个私有地址,路由上可能没有这台主机 |
| NXDOMAIN 或无此类型的负缓存 | 内网解析器现在其实有这个名字 | 负缓存到期前,不会去问新的解析器 |
| 占位地址 | 占位模式已经停用 | 应用若仍握着占位地址,包不会发向该名字的真实主机 |
CDN 那一行和 EDNS 客户端子网 是同一层问题:递归解析器按自己或附带的地址前缀,向权威服务器要答案。缓存把这次选出的地址留住。人离开了那个出口,地址不会跟着路由一起改写。
分离 DNS 决定某个后缀问哪一台解析器。缓存决定这次还问不问。两处要一起看:后缀规则已经指向内网解析器,负缓存仍可能让这个名字继续显示为不存在。
Fake-IP 在本机编一个占位地址来匹配规则。这个地址进了应用自己的缓存之后,停用占位模式也不会把已经握在手里的那一份改成真实地址。
RFC 8767 允许递归解析器在重新查询期间,短暂交出已经过期的记录。这是可选行为。某台公共解析器会不会这样做,以该解析器的说明为准。本文没有逐台测量。
和校验失败、竞速分开
DNSSEC 校验失败返回的是服务器失败,不是一条可继续使用的负缓存。签名没通过时,执行验证的解析器不把地址交给应用。负缓存则是权威方面已经明确「没有这个名字或这种类型」,并给出了可以记住多久。
Happy Eyeballs 在已经返回的地址之间错开尝试。它使用的地址可以来自刚刚的查询,也可以来自还没过期的缓存。缓存里只有 A、没有 AAAA 时,就不会有跨地址族的竞速。
现象对照
| 现象 | 更可能先看什么 |
|---|---|
| 刚连上,内网名字仍报不存在,过一段时间又出现 | 切换前的负缓存还没减到零 |
| 断开后,公司名字仍解析出私有地址,但连不上 | 私有地址的正缓存还在,路由已经不在那张网 |
| 只有浏览器里的页面仍走向旧地址,系统查询已经是新的 | 浏览器有独立缓存,或浏览器用了自己的 DoH |
| 人已经回到本地,某些网站仍连到远处的 CDN | 按出口位置选出的地址还在 TTL 内 |
| 占位地址还在,真实网站却打不开 | Fake-IP 的映射还被应用握着 |
| 失败只维持很短一段时间,且不是「名字不存在」 | 有人缓存了 SERVFAIL。规范把这类缓存的上限定在五分钟,不是每次都会存满 |
核对清单
- 先分清是哪一层还握着旧答案:应用、系统存根解析器,还是递归解析器;
- 再看这条记录是正缓存还是负缓存:有地址,和「不存在」,都会挡住下一次查询;
- 把地址和路由分开:公网地址仍有效时,出口变了是路由的事;
- 内网后缀对照分离 DNS:规则指向新解析器,不表示负缓存已经作废;
- CDN 地址对照解析器位置:远处节点可能只是 TTL 还没结束。