「DNSが引けない」で夜を明かさないために。digの出力を“解読”する現場の技術
ネットワーク障害の現場で、若いエンジニアから「なぜか繋がらないんです」と相談を受けるとき、決まって彼らはブラウザを叩いたり、pingを打ってパケットロスを見ていたりする。もちろんそれも大事だが、現代のインフラの9割は名前解決の裏側で死んでいると言っても過言ではない。
「名前解決が遅い」あるいは「意図しないIPが返ってくる」。この怪現象を切り分ける唯一無二の相棒が dig だ。教科書通りのコマンドを打つのは誰でもできる。重要なのは、dig が吐き出すあの無機質なテキストの「どこを見て、何を判断するか」という嗅覚だ。
今日は、百戦錬磨の現場感覚で dig の深淵を解説する。
—
1. digの出力は「4つの物語」で構成されている
dig の結果は、大きく分けて4つのセクションからなる。これらは単なるデータ列ではなく、DNSサーバーが辿った「経緯」そのものだ。
;; QUESTION SECTION:
;example.com. IN A
;; ANSWER SECTION:
example.com. 3600 IN A 93.184.216.34
;; AUTHORITY SECTION:
example.com. 172800 IN NS a.iana-servers.net.
;; ADDITIONAL SECTION:
a.iana-servers.net. 172800 IN A 199.43.135.53
① QUESTION SECTION:我々の問いかけ
「何を解決したいのか」がここに書かれている。ここが間違っていれば、以降のセクションはすべて無意味だ。タイプ(AなのかMXなのか)やクラス(INが一般的)を確認する。
② ANSWER SECTION:答えそのもの
ここには、DNSキャッシュサーバーや権威サーバーが返した「正解」が入る。TTL(生存期間)にも注目してほしい。もしここが空なら、それは「名前が存在しない(NXDOMAIN)」か「タイムアウト」のどちらかだ。
③ AUTHORITY SECTION:誰が管理しているのか
ここがトラブルシューティングの肝だ。このセクションには、ドメインの権威DNSサーバーの情報が記載されている。再帰的な問い合わせが失敗している場合、このセクションをヒントに、どこまで辿り着けているのかを追いかけることができる。
④ ADDITIONAL SECTION:おまけの親切
権威サーバーのIPアドレスなどがここに記載される。わざわざ別途名前解決をしなくても済むよう、DNSサーバーが気を利かせてくれているわけだ。ここが空だと、追加でDNSルックアップが発生し、パフォーマンスが劣化する。
—
2. 実務で使う「デバッグの定石」
ただ dig example.com と打つだけでは、素人だ。プロは以下のオプションで「何が起きているか」を暴く。
トレースで「迷子」を探す
どこで解決に失敗しているか、ルートサーバーから順に辿るには +trace が必須だ。
# 再帰的な解決プロセスを丸裸にする
dig example.com +trace
これは、パケットがインターネットの階層構造をどう駆け巡っているかを可視化する。途中のネームサーバーが返答を拒否していたり、ルートサーバーへの到達性が悪かったりする場合、一発で判明する。
特定のサーバーを名指しする
システムの内部DNSなのか、ISPのDNSなのか。疑わしいサーバーがあるときは、IPアドレスを直接指定する。
# 8.8.8.8に対して正当性を問う
dig @8.8.8.8 example.com +noall +answer
+noall +answer を付けることで、冗長なヘッダーを省き、純粋な回答だけを抽出できる。シェルスクリプトに組み込む際にも非常に重宝するテクニックだ。
—
3. アプリケーションコードからの「現実的」アプローチ
Web API設計やインフラ運用に携わっているなら、コード側でDNSの振る舞いを意識する必要がある。例えば、PythonでDNSを解決する場合、ライブラリ任せにするとエラーログが不親切になりがちだ。
import dns.resolver
# 特定のDNSサーバーを指定して問い合わせるコード例
resolver = dns.resolver.Resolver()
resolver.nameservers = ['8.8.8.8'] # 外部DNSを明示的に指定
try:
answers = resolver.resolve('example.com', 'A')
for rdata in answers:
print(f"IP Address: {rdata.address}")
except Exception as e:
# 接続障害なのか、DNSレコード欠落なのかをログに吐くのが肝
print(f"DNS Resolution Failed: {e}")
APIのレスポンスが極端に遅い場合、その原因の多くは名前解決のレイテンシか、コネクションプールのDNSキャッシュが古くなっていることにある。curl でデバッグする際も、以下のように名前解決時間を計測する癖をつけておこう。
# 名前解決の時間(time_namelookup)を測定する
curl -w "DNS Time: %{time_namelookup}\n" -o /dev/null -s https://example.com
—
最後に:ネットワークは「嘘をつかない」
DNSのトラブルは、往々にして「設定ミス」か「権限委譲の不整合」だ。dig の結果を眺めていると、時折、パケットがどこで迷子になり、なぜその答えが返ってきたのかという「物語」が見えてくるようになる。
教科書を暗記するのではなく、dig の出力にある数字一つひとつが、ネットワークのどこかのルーターやサーバーからの「返答」であることを意識してほしい。それが、障害対応の最前線で冷静でいられる唯一の秘訣だ。
さあ、次は君のターミナルで dig を叩き、パケットの声を聞いてみてくれ。
コメント