LabHub
学习 学习路径 课程

网络排障

读写并审计 /etc/hosts

在 LabHub 中继续学习

目标

读取、修改并审计 /etc/hosts,亲手确认 getentdig 为何给出不同答案。

为什么重要

只要 /etc/hosts 对应的 nsswitch.conf 配置中,hosts: 行里的 files 位于前面, 系统就会先于 DNS查询该文件。因此,只要 hosts 中残留一条错误记录,无论怎样修复 DNS, 应用仍会访问旧地址。更糟的是,这种事故不会呈现为 DNS 错误——名称能够正常解析, 症状却表现为 connection refused 或 timeout。dig 完全不读取该文件, 于是便会形成“dig 正常,只有应用失败”的迷局。

步骤

  1. 创建 /root/net 目录,从 /etc/hosts 中只选出包含环回地址的行,保存到 /root/net/hosts-loopback.txt。必须同时包含 IPv4(以 127. 开头)和 IPv6(::1)。
  2. /etc/hosts 中添加 10.10.0.11app1.labhub.local(规范名称)、app1(别名)记录,并将 getent hosts app1.labhub.local 的输出保存到 /root/net/getent-app1.txt
  3. 确认使用别名 app1 也能得到相同 IP,并保存到 /root/net/getent-alias.txt
  4. /etc/nsswitch.conf 中以 hosts: 开头的行保存到 /root/net/nsswitch-hosts.txt
  5. /etc/hosts 中添加 IPv6 记录 fd00:cafe::11app6.labhub.local,并将只查询 IPv6 地址的结果保存到 /root/net/getent-v6.txt
  6. /etc/hosts 中分别用两行将同一个名称 web.labhub.local 映射到 10.10.0.2110.10.0.22,再将 getent ahosts web.labhub.local 的输出保存到 /root/net/getent-multi.txt
  7. 审计 /opt/fixtures/nt-hosts/hosts.broken。对于违反以下三条规则的行,将行号本身按升序逐行写入 /root/net/hosts-audit.txt
    • 规则 A:每条记录行的 IP 与名称合计必须包含至少 2 个字段
    • 规则 B:IPv4 地址的每个八位组必须在 0~255 范围内
    • 规则 C:同一个规范名称(第二个字段)不得在文件中出现两次以上
  8. 提交修复第 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

参考

检查环回记录

创建 /root/net 目录,从 /etc/hosts 中只选出包含环回地址的行,保存到 /root/net/hosts-loopback.txt。必须同时包含 IPv4(以 127. 开头)和 IPv6(::1)。

IPv4 环回和 IPv6 环回位于不同的行中,必须将两行都筛选出来。

添加记录并检查解析

/etc/hosts 中添加 10.10.0.11app1.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::11app6.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.2110.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

规则包括以下几项:字段少于 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,实践中通常更适合把它修正为正确值。