读写并审计 /etc/hosts
目标
读取、修改并审计 /etc/hosts,亲手确认 getent 与 dig 为何给出不同答案。
为什么重要
只要 /etc/hosts 对应的 nsswitch.conf 配置中,hosts: 行里的 files 位于前面,
系统就会先于 DNS查询该文件。因此,只要 hosts 中残留一条错误记录,无论怎样修复 DNS,
应用仍会访问旧地址。更糟的是,这种事故不会呈现为 DNS 错误——名称能够正常解析,
症状却表现为 connection refused 或 timeout。dig 完全不读取该文件,
于是便会形成“dig 正常,只有应用失败”的迷局。
步骤
- 创建
/root/net目录,从/etc/hosts中只选出包含环回地址的行,保存到/root/net/hosts-loopback.txt。必须同时包含 IPv4(以127.开头)和 IPv6(::1)。 - 在
/etc/hosts中添加10.10.0.11→app1.labhub.local(规范名称)、app1(别名)记录,并将getent hosts app1.labhub.local的输出保存到/root/net/getent-app1.txt。 - 确认使用别名
app1也能得到相同 IP,并保存到/root/net/getent-alias.txt。 - 将
/etc/nsswitch.conf中以hosts:开头的行保存到/root/net/nsswitch-hosts.txt。 - 在
/etc/hosts中添加 IPv6 记录fd00:cafe::11→app6.labhub.local,并将只查询 IPv6 地址的结果保存到/root/net/getent-v6.txt。 - 在
/etc/hosts中分别用两行将同一个名称web.labhub.local映射到10.10.0.21和10.10.0.22,再将getent ahosts web.labhub.local的输出保存到/root/net/getent-multi.txt。 - 审计
/opt/fixtures/nt-hosts/hosts.broken。对于违反以下三条规则的行,将行号本身按升序逐行写入/root/net/hosts-audit.txt。- 规则 A:每条记录行的 IP 与名称合计必须包含至少 2 个字段
- 规则 B:IPv4 地址的每个八位组必须在 0~255 范围内
- 规则 C:同一个规范名称(第二个字段)不得在文件中出现两次以上
- 提交修复第 7 步中所有问题后的最终文件
/root/net/hosts.final。保留原有的正常记录,将db01.labhub.local修正为10.20.30.13,将bad.labhub.local修正为10.20.30.18,将缺少名称的行补成10.20.30.14 log01.labhub.local log01,并把具有重复规范名称的行改为规范名称web01-old.labhub.local。
参考
getent hosts <이름>使用与应用相同的解析路径,而dig +short <이름>只直接查询 DNS 服务器。- 使用
getent ahostsv6 <이름>可以只查看 IPv6 结果。 - 使用
grep -n或awk '{print NR}'计算行号。注释和空行也计入行号。 - 常见错误 1:在第 7 步中把相同 IP 出现两次视为问题。一个 IP 对应多个名称是正常的。
- 常见错误 2:第 2 步中只用空格而不用制表符也能工作,但把名称写在 IP 前面则无法解析。顺序始终是 IP 在前。
检查环回记录
创建 /root/net 目录,从 /etc/hosts 中只选出包含环回地址的行,保存到 /root/net/hosts-loopback.txt。必须同时包含 IPv4(以 127. 开头)和 IPv6(::1)。
IPv4 环回和 IPv6 环回位于不同的行中,必须将两行都筛选出来。
添加记录并检查解析
在 /etc/hosts 中添加 10.10.0.11 → app1.labhub.local(规范名称)、app1(别名)记录,并将 getent hosts app1.labhub.local 的输出保存到 /root/net/getent-app1.txt。
getent hosts 使用与应用相同的路径解析名称,结果的第一个字段是 IP。
确认别名也能解析
确认使用别名 app1 也能得到相同 IP,并保存到 /root/net/getent-alias.txt。
hosts 一行中的第二个字段是规范名称,从第三个字段开始是别名。别名也应解析到相同 IP。
检查解析顺序
将 /etc/nsswitch.conf 中以 hosts: 开头的行保存到 /root/net/nsswitch-hosts.txt。
只需以 hosts 开头的那一行。该行中的第一个来源是什么,是本实验的关键。
处理 IPv6 记录
在 /etc/hosts 中添加 IPv6 记录 fd00:cafe::11 → app6.labhub.local,并将只查询 IPv6 地址的结果保存到 /root/net/getent-v6.txt。
hosts 文件并非只能包含 IPv4。写入 IPv6 地址后,用 getent hosts <이름> 进行确认。
如果你想到了 getent ahostsv6,说明方向很好,但在这个环境中它会返回空值。glibc 的 ahosts 系列在查询时附加 AI_ADDRCONFIG,而该标志只有在本机至少存在一个全局作用域 IPv6 地址时才会查询 IPv6。lo 的 ::1 属于 host 作用域,不会被计入,因此连 getent ahostsv6 ::1 也会返回空值。
这不是刻意设置的陷阱,而是实践中会原样遇到的现象——“明明写在 hosts 里,为什么查不到”的常见答案就是它。getent hosts 使用另一条路径(gethostbyname2),不会经过该标志。
一个名称对应多个 IP
在 /etc/hosts 中分别用两行将同一个名称 web.labhub.local 映射到 10.10.0.21 和 10.10.0.22,再将 getent ahosts web.labhub.local 的输出保存到 /root/net/getent-multi.txt。
可以在两行中为同一名称分别填写不同 IP。观察 getent ahosts 返回多少行。
审计损坏的 hosts 文件
审计 /opt/fixtures/nt-hosts/hosts.broken。对于违反以下三条规则的行,将行号本身按升序逐行写入 /root/net/hosts-audit.txt。
- 规则 A:每条记录行的 IP 与名称合计必须包含至少 2 个字段
- 规则 B:IPv4 地址的每个八位组必须在 0~255 范围内
- 规则 C:同一个规范名称(第二个字段)不得在文件中出现两次以上
规则包括以下几项:字段少于 2 个的行、IPv4 八位组超过 255 的行,以及再次使用此前已经出现过的规范名称的行。行号从文件顶部开始按 1 计数,其中包含注释和空行。
提交整理后的最终文件
提交修复第 7 步中所有问题后的最终文件 /root/net/hosts.final。保留原有的正常记录,将 db01.labhub.local 修正为 10.20.30.13,将 bad.labhub.local 修正为 10.20.30.18,将缺少名称的行补成 10.20.30.14 log01.labhub.local log01,并把具有重复规范名称的行改为规范名称 web01-old.labhub.local。
该文件必须消除审计中发现的所有问题。与其删除错误 IP,实践中通常更适合把它修正为正确值。