用 dig 挖 DNS
目标
用 dig 按记录类型查询,读取 TTL 和否定缓存,并亲手制造出 getent 与 dig 答案分歧的情况。
为什么重要
dig 的输出要先读 status 和 flags。NXDOMAIN(名称本身不存在)和 NOERROR + ANSWER 0(名称存在但没有该类型)是完全不同的情况,应对方式也不同。没有 aa 标志,答案就来自缓存,所以 TTL 会减少。而且 dig 不看 /etc/hosts,所以对同一个名称可能给出与 getent 不同的答案——这个差异正好指出了原因所在的位置。
步骤
- 创建
/root/dns目录,把/etc/resolv.conf中以nameserver开头的行保存到/root/dns/nameserver.txt。 - 只把
example.com的 A 记录值保存到/root/dns/a.txt。文件中至少要有一行 IPv4 地址。 - 把
google.com的MX、NS、TXT分别保存到/root/dns/mx.txt、/root/dns/ns.txt、/root/dns/txt.txt。三个文件都不能为空。 - 只输出
example.com的应答部分并保存到/root/dns/ttl1.txt,等待 5 秒以上后用同样的方法生成/root/dns/ttl2.txt。第二个 TTL 不能大于第一个。 - 把
8.8.8.8的反向查询结果保存到/root/dns/ptr.txt。 - 查询
labhub-does-not-exist-9137.invalid,把完整输出保存到/root/dns/nxdomain.txt。文件中必须同时包含status: NXDOMAIN和 SOA 记录。 - 在
/etc/hosts中添加10.77.0.1 www.example.com后,把getent hosts www.example.com的结果保存到/root/dns/getent-www.txt,把dig +short www.example.com的结果保存到/root/dns/dig-www.txt。两个结果必须不同。 - 把
/root/dns/report.txt写成以下 5 行。NAMESERVERS=<line count of the step-1 file>/A_COUNT=<line count of the step-2 file>/PTR=<name from step 5, without the trailing dot>/HOSTS_WINS=<IP from the step-7 getent result>/DNS_SAYS=<first IP from the step-7 dig result>
参考
- 组合使用
dig +short、dig +noall +answer、dig -x <IP>、dig -t MX <name>,本实验的大部分内容就能完成。 - 在第 4 步中,TTL 是
+noall +answer输出的第二列。 - 在第 6 步中,SOA 出现在 AUTHORITY 部分。也可以用
+noall +authority单独查看。 - 常见错误 1:如果第 7 步中加入 hosts 的 IP 与实际 DNS 应答相同,这一步就失去了意义。请使用私有网段地址。
- 常见错误 2:
dig结果为空,说明没有该类型的记录。请查看status,区分是 NXDOMAIN 还是 NOERROR。 - 第 6 步使用
.invalid的原因:有些区域不会对不存在的名称返回 NXDOMAIN。在本实验 Pod 中查询example.com、example.org、example.net下不存在的名称时,返回的是status: NOERROR和 SOA(2026-11-06 实测——一种减少否定应答的 DNS 服务)。.invalid是标准规定为“不存在”的名称,因此总是返回 NXDOMAIN。
读取解析器设置
创建 /root/dns 目录,把 /etc/resolv.conf 中以 nameserver 开头的行保存到 /root/dns/nameserver.txt。
只需要 resolv.conf 中以 nameserver 开头的行。可能有多行。
正向查询
只把 example.com 的 A 记录值保存到 /root/dns/a.txt。文件中至少要有一行 IPv4 地址。
只需要值时,有简短输出的选项。A 记录必须是 IPv4 地址格式。
按记录类型查询
把 google.com 的 MX、NS、TXT 分别保存到 /root/dns/mx.txt、/root/dns/ns.txt、/root/dns/txt.txt。三个文件都不能为空。
dig 可以用 -t 指定类型,也可以直接把类型写在名称后面。MX 的值是优先级数字和主机名的组合。
观察 TTL 减少
只输出 example.com 的应答部分并保存到 /root/dns/ttl1.txt,等待 5 秒以上后用同样的方法生成 /root/dns/ttl2.txt。第二个 TTL 不能大于第一个。
只输出 answer 部分时,TTL 在第二列。隔一小段时间执行两次相同的查询。
反向查询
把 8.8.8.8 的反向查询结果保存到 /root/dns/ptr.txt。
dig 有一个专用选项,输入 IP 就会查找 PTR。结果是以点结尾的名称。
不存在的名称与否定缓存
查询 labhub-does-not-exist-9137.invalid,把完整输出保存到 /root/dns/nxdomain.txt。文件中必须同时包含 status: NXDOMAIN 和 SOA 记录。
status 在头部行中。SOA 出现在 AUTHORITY 部分,最后一个数字是 MINIMUM。
getent 与 dig 分歧的地方
在 /etc/hosts 中添加 10.77.0.1 www.example.com 后,把 getent hosts www.example.com 的结果保存到 /root/dns/getent-www.txt,把 dig +short www.example.com 的结果保存到 /root/dns/dig-www.txt。两个结果必须不同。
只有 hosts 中的 IP 与 DNS 给出的 IP 不同,这一步才有意义。分别保存两个结果。
有一个陷阱。getent hosts <name> 会先用 IPv6 查询,只有没有答案时才改用 IPv4 再查。可是加入 hosts 的只有一行 IPv4,所以如果该名称有 AAAA 记录,v6 查询会越过 hosts 发往 DNS,先输出 IPv6 地址。 看起来像是 hosts 被忽略了,其实并非如此——用 getent ahostsv4 <name> 只查询 v4 系列,就会原样得到 hosts 中的值。这一步请使用后者。
查询综合报告
把 /root/dns/report.txt 写成以下 5 行。
NAMESERVERS=<line count of the step-1 file> / A_COUNT=<line count of the step-2 file> / PTR=<name from step 5, without the trailing dot> / HOSTS_WINS=<IP from the step-7 getent result> / DNS_SAYS=<first IP from the step-7 dig result>
把前面各步的结果汇总成 键=值 即可。计数项按行数统计就足够了。