给客户端下发解析器地址,只决定查询发往哪里,并不决定解析器会看到哪个来源。路由、转发和地址转换在两端之间轮流插手。一份面向来源问题的操作手册会逐跳跟随查询,并记录每个观察点实际看到了什么。顺序很重要,因为在观察之前下的结论,只是格式更漂亮的猜测。

先写下整体安排,再去收集证据

有四个位置能告诉你 DNS 来源的信息,而且它们说的并不相同。客户端内核知道自己会用哪个源地址,转发器知道自己向上游发了什么,做转换的设备知道自己改写了什么,接收方解析器知道实际到达的是什么。在收集任何材料之前,先写下这四个位置里你真正能接触到哪几个。

Observation pointWhat it can proveWhat it cannot proveHow to read it
client kernelwhich source address it would use for that resolveranything a device in between rewroteip route get against the resolver address
forwarderthat it sent an upstream query, and from which sourcewhat the client originally asked forits own log and its cache state
translating devicethat a source was rewritten, and to whatwhether the query was legitimateNAT policy and its counters
receiving resolverthe address that actually arrivedwhich client behind that address askeda scoped capture on port 53

也把你的预期写下来,包括你认为正在使用的解析器。分裂路由可能把查询送到完全不同的地方,缓存也可能完全不经过上游就给出应答,所以只留在脑子里的假设撑不过第一次意外。把声明的设计和实测的路径放在同一份记录的两个独立栏目里;两者对不上时,你就找到了值得追下去的问题。

确认查询究竟是哪个进程发出的

从客户端开始:记下解析器地址、查询名和时间,再确认是哪个进程发出的。下面第一行会指出持有 UDP 套接字的进程,这正是这个小标题承诺的检查。如果那个进程是浏览器辅助进程或容器运行时,而不是系统解析器,那么后面的整条链路描述的就是没人问过的路径。

ss -tunp 'dport = :53'
dig @10.20.30.53 host.corp.example +noall +answer
ip route get 10.20.30.53

在多网卡主机上,先弄清内核为这个目的地会选择哪个源地址,再去别处找答案。这是路径完全由你掌控的最后一个点,也是你要和解析器报告的值作比较的那个值。对不上,说明中间有设备改写了报文,或者发出的是两个不同的查询。

测试名要留在内部,因为把内部名交给公共解析器,既不能证明内部路径的任何事情,又公开了一个本不必公开的名字。开了安全 DNS 的浏览器根本不会出现在那份套接字列表里,而这个缺席本身就是答案。

转发器会再发一次独立的查询

转发器把一次交互变成两次。下游请求到达后,转发器会用它自己选定的地址向上游发出自己的查询。决定上游解析器看到什么的是它的配置,而不是客户端。

dnsmasq 手册正因如此值得一读:它写明了转发器如何选择上游服务器、如何绑定监听侧,而这套安排里没有任何一环把客户端来源带上去。所以解析器日志里出现网关地址是正常现象,不是故障证据。缺席同样容易被误读,因为缓存命中不会产生任何上游查询,看起来和从未到达的查询一模一样。在得出这两个结论中的任何一个之前,先读转发器的配置和它的缓存状态。两个问题,两个该看的地方。

到接收方解析器上读来源

唯一能定论的观察发生在服务器一侧。凡是从客户端接口列表推断出来的东西,在解析器报告实际到达者之前都只是假设。

tcpdump -ni any port 53 and host 10.20.30.53

在解析器主机上抓包,抓包要短、要有范围,并存放在策略允许的地方。如果观察到的来源是转换后的地址,下一个问题就是哪台设备做了转换、它的策略是不是预期的那一份。抓包回答的是到达了什么,并不解释策略为什么允许。记录里要写明观察点和跳数,因为关于网关的隐私结论针对的是那一跳,而不是整条路径。

把结论写成路径,而不是一个地址

记录客户端、解析器、任何转发器、每一跳观察到的来源,以及管辖它的策略。这样一份记录能在不再抓包的情况下回答日后的大部分问题。把它画成链条,因为地址清单会掩盖哪一跳产出了哪一个。

把日期、客户端版本和配置版本附在图上,后来的读者才能判断它是否仍然成立。把传输来源和服务处理的其他内容分开,因为看到一个网关地址,并不能说明还保留了别的什么。解析器的位置同样不能说明是哪个客户端来问的。把这些结论分开,才是让判断经得起复核的关键。

相关文章