私有 Route 53 区域会替换某个名称的答案,而不是与公网记录合并,因此人们往往在最糟糕的时刻被打个措手不及。为一个内部记录添加 api.example.net ,放在归属于 example.net 的私有区域中,再把它关联到某个 VPC,该父名称下的其他所有名称从此只由私有区域作答。昨天还能访问 www.example.net 的客户端,今天却收到否定回答。下面的排查从这个失败的查询出发,一路追到作出应答的区域。

从查询开始,而不是从控制台开始

在报告问题的客户端上复现故障,并记录准确的名称和记录类型。对 A 失败的名称,对 AAAA 也许仍能解析,而重试缓存名称的浏览器会掩盖究竟是哪一个坏了。查询要跑两次:一次走客户端真正使用的解析器,一次走绕过它的抓包追踪。

dig +short api.example.net
dig www.example.net +noall +comments +authority
resolvectl query www.example.net

第二条命令才是关键。它的状态行和 authority 段会指出产生答案的区域,因此你能把私有区域的否定回答与超时、端口被封锁或从未收到查询的解析器区分开。 resolvectl 还会显示主机实际询问的上游服务器,而这个上游往往并不是你以为 VPN 推送的那个解析器。

如果带追踪的查询返回公网地址,而不带追踪的查询没有,说明公网记录完好,答案来自私有视图。仅凭这一项对比,就能判断本页余下部分哪一半适用于你。

读出是哪个区域作答

携带 NXDOMAIN 且在 authority 段带有私有区域 SOA 的响应,是来自该区域的确定答案,而不是查询失败。Route 53 Resolver 因为名称匹配选中了私有托管区域,随后找不到所请求类型的记录,按文档说明的行为是返回否定回答,而不是把问题转发给公网 DNS。

选择遵循具体程度。当多个私有命名空间重叠时,最具体且匹配的区域胜出,更宽泛的私有父区域不会为子区域缺失的名称提供第二次机会。转发规则又叠加了一层:针对某个域的 Resolver 规则可以压过私有托管区域的关联。在下结论说某个区域是空的之前,先把关联和规则列出来。

aws route53 list-hosted-zones-by-name --dns-name example.net.
aws route53 list-resource-record-sets --hosted-zone-id Z0EXAMPLEID --query "ResourceRecordSets[?Type=='A'].[Name,ResourceRecords[0].Value]"

两条命令都需要拥有该区域账户的凭证,第二条还要用第一条返回的区域 ID。请换成你自己的 ID;上面的占位符故意不是真的。

为什么私有区域胜出

正是关联让区域对 VPC 可见,而该 VPC 中的解析器负责应用它。未与客户端流量来源 VPC 关联的私有区域完全不起作用,而关联到错误的 VPC 则会给错误的人群返回私有答案。编辑记录前先检查关联列表,因为区域可能配置正确却仍然不可见。

重叠的命名空间是第二个困惑来源。用于 example.net 的私有区域和用于 api.example.net 的私有区域都会匹配 API 查询,更具体的那个作答。想要狭窄的内部命名空间时这很有用,可当狭窄区域缺少较宽区域已有的记录时就很危险。私有托管区域的相关注意事项在 Route 53 文档 中既描述了向下落空的行为,也描述了规则优先级,值得在添加第二个重叠区域之前读一遍。

这些都改变不了公网区域。公网解析器仍能正确回答公网记录,所以 VPC 之外的所有人看到的都像是客户端问题。

在添加记录之前先选好命名空间

如果只有一簇新的内部服务需要私有名称,就给它一个专用的私有子域名,让公网父域保持原样。像 internal.example.net 这样的名称不会遮蔽 www.example.net,缺失记录的影响范围仅限于你为此目的造出来的名称。代价是现有 URL 与证书可能和新名称对不上。

当公网与私有用户必须保留同一个主机名时,拆分视图 DNS 才是受支持的设计,它要求你显式维护每个视图中的记录。一个只放一条记录的宽泛私有区域并不能保留该区域下的公网依赖,它只是用一条记录的区域替换了那些依赖。

在把一批客户端指向私有视图之前,先盘点应用真正调用的名称。登录主机、静态资源主机、重定向目标和 API 端点最先出问题,而且它们通常散落在多个团队的记录里。

先追踪解析器路径,再追踪路由

只有当查询能到达带关联的解析器时,笔记本电脑才能看到私有视图。在 VPN 服务器上改 hosts 文件不会向已连接的客户端发布任何内容,而配置了公网解析器的客户端在隧道开启期间仍会继续拿到公网答案。先确认客户端拿到的解析器地址,然后从客户端而不是从服务器重跑查询。

名称解析成功之后,要把到返回地址的路径作为单独一步来测,例如用 ip route get 对查询返回的地址执行。私有答案正确但到该地址没有路由,是路由问题;回答记录不存在,则是 DNS 视图问题。把两者当成一个问题,修出来的东西往往不牢。服务的主机名 TLS 与证书校验不要动,因为私有地址只改变连接去往何处,并不改变哪张证书有效。

最后把区域、关联、解析器以及你验证过的名称写进变更记录。这样下一位添加记录的人就知道哪个命名空间对这批客户端有效。

相关文章