TT Lab
はじめる
学ぶ 学習パス コース

ネットワーク基礎 — Linux VM で手を動かす

名前が解決される道を最後まで辿る

TT Labで続きを見る

このラボはVM上で動きます

Ubuntu 24.04ではsystemd-resolvedが名前解決を担当します。そこにdnsmasqで自分のDNSサーバーをもう1つ立て、2つの層を行き来しながら、名前がどこで答えを得るのかを見ます。dnsmasqはすでにインストールされていますが、サービスが失敗したままです。その理由を探すのがステップ3です。

目標

/etc/resolv.confのスタブアドレスが何か、本当の上流サーバーはどこか、自分のDNSサーバーを特定のドメインだけにつなぐにはどうするか、/etc/hostsがなぜDNSに優先されるのかを、コマンドで確認します。

なぜ重要なのか

「つながらない」の最初の分かれ道が名前です。ところが最近のLinuxでは、名前解決は1つの層ではありません。アプリケーションはlibcのgetaddrinfoを呼び、それはnsswitch.confの順にまず/etc/hostsを見て、次にresolv.confのスタブ(127.0.0.53)に尋ね、スタブはリンクごとの設定を見て上流へ転送します。digはこのうち最後の段階だけを直接叩きます。そのため、digは通るのにcurlは通らないということが実際に起き、どの層が違うのかを知って初めて直せます。

ステップ

  1. /etc/resolv.confが指す実際のファイルパスとnameserverの行を /root/dns/resolv.txt に保存してください。
  2. スタブが実際に尋ねる上流DNSサーバーのアドレスを、/root/dns/upstream.txt にupstream=<주소>の1行で保存してください(プレースホルダーはアドレスです)。
  3. dnsmasqがなぜ起動しないのかを調べ、ポート53を掴んでいるプロセスを示すssの出力を /root/dns/port53.txt に保存してください。
  4. ダミーインターフェースdns0に10.53.0.1/24を付け、/etc/dnsmasq.d/lab.conf で、dnsmasqが10.53.0.1だけで待ち受け、app.lab.internal→10.53.0.10、db.lab.internal→10.53.0.20を答えるようにして、サービスを復旧させてください。
  5. dig @10.53.0.1 app.lab.internalの全出力を /root/dns/dig.txt に保存してください。
  6. resolvectlでdns0リンクにDNSサーバー10.53.0.1とルーティングドメイン~lab.internalを指定して、getent hosts app.lab.internalが通るようにし、resolvectl status dns0を /root/dns/link.txt に保存してください。
  7. /etc/hostsに10.53.0.99 db.lab.internalを入れ、getentとdig @10.53.0.1の答えを /root/dns/hosts.txt にgetent=・dig=の2行で保存してください。
  8. /root/dns/report.md に、stub=・upstream=・local=の3行、dnsmasqのクエリログからapp.lab.internalの行1つ、そして/etc/hostsがDNSに優先される理由を書いてください。

参考

resolv.confの正体

/etc/resolv.confが指す実際のファイルパスとnameserverの行を /root/dns/resolv.txt に保存してください。

readlink -f /etc/resolv.confがシンボリックリンクの先の本当のパスを返します。grep nameserver /etc/resolv.confでスタブのアドレスを見ます。両方を1つのファイルに入れてください。

本当のサーバーはどこか

スタブが実際に尋ねる上流DNSサーバーのアドレスを、/root/dns/upstream.txt にupstream=<주소>の1行で保存してください(プレースホルダーはアドレスです)。

resolvectl statusのリンクの項目にCurrent DNS Serverがあります。デフォルトルートのインターフェース(enp1s0)の値です。resolvectl dns enp1s0のほうが短く済みます。

dnsmasqはなぜ起動しないのか

dnsmasqがなぜ起動しないのかを調べ、ポート53を掴んでいるプロセスを示すssの出力を /root/dns/port53.txt に保存してください。

systemctl status dnsmasqとjournalctl -u dnsmasqにAddress already in useがあります。誰が掴んでいるかはss -ulpn 'sport = :53'で確認します。-pがプロセス名を表示します(rootで実行する必要があります)。

自分のDNSサーバーを立てる

ダミーインターフェースdns0に10.53.0.1/24を付け、/etc/dnsmasq.d/lab.conf で、dnsmasqが10.53.0.1だけで待ち受け、app.lab.internal→10.53.0.10、db.lab.internal→10.53.0.20を答えるようにして、サービスを復旧させてください。

ip link add dns0 type dummyのあとにアドレス設定とUPを行います。設定はlisten-address=10.53.0.1とbind-interfacesでそのアドレスだけを掴ませ、address=/app.lab.internal/10.53.0.10のように名前を固定します。no-resolvは上流を使わないという意味です。終わったらsystemctl restart dnsmasqのあとにsystemctl is-active dnsmasqを実行します。

digで直接尋ねる

dig @10.53.0.1 app.lab.internalの全出力を /root/dns/dig.txt に保存してください。

@서버はresolv.confを無視して、そのサーバーに直接尋ねます(プレースホルダーはサーバーのアドレスです)。出力のANSWER SECTIONにAレコードが、ヘッダーにstatus: NOERRORが表示されている必要があります。

スタブに自分のサーバーをつなぐ

resolvectlでdns0リンクにDNSサーバー10.53.0.1とルーティングドメイン~lab.internalを指定して、getent hosts app.lab.internalが通るようにし、resolvectl status dns0を /root/dns/link.txt に保存してください。

resolvectl dns dns0 10.53.0.1とresolvectl domain dns0 '~lab.internal'を実行します。~が付いたドメインは、「このドメインのクエリは、このリンクのサーバーへ送る」というルーティングルールです。確認はgetent hosts app.lab.internalで、10.53.0.10が出力される必要があります。

/etc/hostsが勝つ

/etc/hostsに10.53.0.99 db.lab.internalを入れ、getentとdig @10.53.0.1の答えを /root/dns/hosts.txt にgetent=・dig=の2行で保存してください。

echo '10.53.0.99 db.lab.internal' >> /etc/hostsを実行します。そのあとgetent hosts db.lab.internal | awk '{print $1}'とdig @10.53.0.1 db.lab.internal +shortを実行します。2つの値は異なります。それがこのステップの要点です。

学んだこと

/root/dns/report.md に、stub=・upstream=・local=の3行、dnsmasqのクエリログからapp.lab.internalの行1つ、そして/etc/hostsがDNSに優先される理由を書いてください。

stubはステップ1のnameserver、upstreamはステップ2の値、localは自分のdnsmasqのアドレスです。ログはjournalctl -u dnsmasq --no-pager | grep 'query\[A\] app.lab.internal'で取り出します。理由には、nsswitchまたはfilesという語を含める必要があります。