/etc/hostsを読み書きし監査する
目標
/etc/hostsを読み、直し、監査します。そして、getentとdigがなぜ違う答えを返すのかを、手で確認します。
なぜ重要なのか
/etc/hostsは、nsswitch.confのhosts:行でfilesが前にある限り、DNSより先に見られます。そのため、hostsに間違った行が1つ残っていると、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の2つのIPにそれぞれ1行ずつ追加し、getent ahosts web.labhub.localの出力を/root/net/getent-multi.txtに保存してください。/opt/fixtures/nt-hosts/hosts.brokenを監査してください。次の3つのルールに違反している行番号だけを、昇順に1行に1つずつ/root/net/hosts-audit.txtに書いてください。- ルールA: すべてのエントリ行は、IPと名前を合わせて2つ以上のフィールドを持っている必要があります
- ルールB: IPv4アドレスの各オクテットは0–255である必要があります
- ルールC: 同じ正規名(2番目のフィールド)がファイルの中に2回以上現れてはいけません
- ステップ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が2回出てくる行を問題として数えてしまう場合です。1つのIPに複数の名前を付けるのは正常です。
- よくある間違い2: ステップ2で、タブの代わりにスペースだけを使っても動作しますが、名前をIPの前に書くと解決されません。順序は常にIPが先です。
ループバックエントリの確認
/root/netディレクトリを作成し、/etc/hostsからループバックアドレスを持つ行だけを選んで/root/net/hosts-loopback.txtに保存してください。IPv4(127.で始まる)とIPv6(::1)の両方が入っている必要があります。
IPv4のループバックとIPv6のループバックは、別々の行にあります。2行とも選び出す必要があります。
エントリを追加して名前解決を確認する
/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の1行で、2番目のフィールドが正規名、3番目以降が別名です。別名も同じIPに解決されるのが正常です。
解決順序の確認
/etc/nsswitch.confからhosts:で始まる行を/root/net/nsswitch-hosts.txtに保存してください。
hostsで始まる行が1つあれば十分です。その行で最初のソースが何かが、このラボの核心です。
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アドレスが1つでもあるときだけIPv6を問い合わせます。loの::1はhostスコープなので数えられず、getent ahostsv6 ::1ですら空の値です。
これは落とし穴ではなく、実務でそのまま出会う現象です。「hostsに確かに書いたのに、なぜ出てこないのか」のよくある答えがこれです。getent hostsは別の経路(gethostbyname2)なので、このフラグの影響を受けません。
1つの名前に複数のIP
/etc/hostsに、web.labhub.localという同じ名前を10.10.0.21と10.10.0.22の2つのIPにそれぞれ1行ずつ追加し、getent ahosts web.labhub.localの出力を/root/net/getent-multi.txtに保存してください。
同じ名前を2行に、それぞれ別のIPで書けます。getent ahostsが何行返すか見てください。
壊れたhostsの監査
/opt/fixtures/nt-hosts/hosts.brokenを監査してください。次の3つのルールに違反している行番号だけを、昇順に1行に1つずつ/root/net/hosts-audit.txtに書いてください。
- ルールA: すべてのエントリ行は、IPと名前を合わせて2つ以上のフィールドを持っている必要があります
- ルールB: IPv4アドレスの各オクテットは0–255である必要があります
- ルールC: 同じ正規名(2番目のフィールド)がファイルの中に2回以上現れてはいけません
ルールは4つです。フィールドが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は、消すよりも正しい値に直すほうが現実的です。