DNSの「迷子」を秒速で暴く!ベテランNOCエンジニアが教える dig ショートカットオプションの極意
夜中の2時。PagerDutyのけたたましいアラート音で跳び起きると、監視モニターには「API Gateway 502 Bad Gateway」の文字。チャットには「外部決済APIへの疎通が取れなくなっています!」という開発チームからの悲鳴。
こういう修羅場で、君たちは真っ先に何をする?
「とりあえず ping を打つ」「ブラウザでリロードしてみる」――もしそう答えたなら、まだまだ若造だな。ネットワークエンジニア、そしてインフラを預かる者にとって、名前解決の裏側で何が起きているかを暴くための最強の武器は、他でもない dig コマンドだ。
特に、DNSのレコードが変わったのに反映されない、あるいは「なぜか特定の環境からだけ名前解決できない」という泥沼のトラブルにおいて、dig の標準出力だけを眺めていてもらチがあかない。ルートサーバーから権威DNSサーバーまでのバトンリレーを丸裸にする +trace、結果だけを美しく抽出しスクリプトに組み込める +short、そして最速でマスターネームサーバーを特定する +nssearch。
今回は、数々の修羅場をくぐり抜けてきた私が、実務の現場で本当に使えるこれらのショートカットオプションの裏側の挙動と、トラブルシューティングのノウハウを徹底的に伝授しよう。
—
1. なぜDNSトラブルは厄介なのか?(RFCと実際の通信フロー)
DNS(Domain Name System)は、人間が理解しやすいドメイン名(例: api.example.com)を、マシンが理解するIPアドレスに翻訳する、インターネットの羅針盤だ。RFC 1034およびRFC 1035でその基本アーキテクチャが規定されて以来、階層的な分散データベースとして動き続けている。
しかし、この「階層構造」と「キャッシュ」こそが、障害時のインフラエンジニアを悩ませる元凶となる。
再帰問い合わせと反復問い合わせのシーケンス
クライアント(例えば、君のローカルPCやAPIサーバー)が dig api.example.com を叩いたとき、背後では次のようなドラマが繰り広げられている。
[Client] ---> (再帰問い合わせ) ---> [フルスタブリゾルバー (8.8.8.8等)]
|
+-------------------------------+-------------------------------+
| (1. ルートサーバーへ聞いてくれと返される、または代わりに聞きに行く)
v
[Root Server (.)] ---> 「.comのサーバーはここだ」
|
v
[TLD Server (.com)] ---> 「example.comの権威サーバーはここだ」
|
v
[Authoritative Server (ns.example.com)] ---> 「答えは 192.0.2.1 だ!」
1. フルスタブリゾルバーへの再帰問い合わせ(Recursive Query):
クライアントは手元のキャッシュDNS(ISPのDNSやGoogle Public DNS 8.8.8.8 など)に対し、「全部調べて教えてくれ!」と丸投げする。
2. ルートサーバーからの反復問い合わせ(Iterative Query):
リゾルバーはまずルートサーバー(.)に問い合わせる。ルートサーバーは「.com のゾーンならあそこのサーバーが知っているよ」と紹介状(Referral)を返す。
3. TLDサーバー、権威サーバーへの追跡:
リゾルバーはその紹介状を元に .com のトップレベルドメイン(TLD)サーバーへ聞きに行き、最終的に example.com のゾーンを管理する権威ネームサーバー(Authoritative DNS Server)にたどり着いて、ようやくIPアドレスを手に入れる。
このどこかのステップで、TTLのキャッシュが腐っていたり、親ゾーンと子ゾーンのグルーーサーバー(NSレコード)の不整合(いわゆる「Glue Recordの崩壊」)が起きていると、名前解決は一瞬で迷子になる。
—
2. 実務で即座に使える! dig ショートカットオプション3選
ここからが本題だ。標準の dig では情報量が多すぎてノイズに埋もれてしまう。現場で泥をかぶるエンジニアが愛用する3つのオプションをマスターしてほしい。
① +trace:ルートからのバトンリレーを完全追跡する
「レコードを書き換えたのに、なぜか古いIPにアクセスしにいってしまう」というキャッシュ汚染や設定ミスを疑うとき、一撃で原因を特定できるのが +trace オプションだ。
実際のコマンド例
dig +trace api.example.com A
通信の裏側と出力の読み方
このオプションを叩くと、dig はあえてOSやリゾルバーのキャッシュを無視し、自分でルートサーバー(a.root-servers.net など)に直接最初のパケットを投げ、そこから自力でバトンリレーを追いかけ始める。
出力結果のイメージを見てみよう:
; <<>> DiG 9.16.1-Ubuntu <<>> +trace api.example.com A
;; global options: +cmd
. 5h17m35s IN NS a.root-servers.net.
... (中略: ルートからの応答) ...
com. 2dIN NS a.gtld-servers.net.
... (中略: TLDからの応答) ...
example.com. 1dIN NS ns1.example.com.
example.com. 1dIN NS ns2.example.com.
api.example.com. 300 IN A 192.0.2.1
;; Received 56 bytes from 192.0.2.1#53(ns1.example.com) in 12 ms
【シニアの眼】
ここで注目すべきは、「どの権威サーバーが実際に応答しているか」だ。もし、自社で Route53 に移行したはずなのに、途中のトレース結果がいつまでも前段のオンプレミスDNSを指していたら、それは親ゾーン(お名前.comやGoDaddyなどのregistrar)でのNSレコードの変更(委譲設定)が漏れている証拠だ。この一撃で、どこに原因があるかが一発で判明する。
—
② +short:スクリプト・自動化の強い味方
障害対応やCI/CDパイプライン、あるいはヘルスチェックの自動化スクリプトを書くとき、dig の冗長なヘッダーやフッター(;; QUESTION SECTION: や ;; AUTHORITY SECTION: など)は邪魔でしかない。必要なのは「IPアドレスそのもの」だけだ。
実際のコマンド例
dig +short api.example.com A
出力例
192.0.2.1
これだけだ。余計な文字列を一切出力しないため、シェルスクリプトやPythonからsubprocessで叩くときに極めて親和性が高い。
実務での活用例:Pythonスクリプトによる死活・IP一致チェック
インフラ自動化やAPIのデプロイ検証で、正しくDNSが切り替わったかを検知するPythonスニペットを書くならこうだ。
import subprocess
import sys
def check_dns_resolution(domain, expected_ip):
"""dig +short を使って指定ドメインの名前解決結果を取得し、
期待するIPと一致するか検証する実用的な関数。
"""
try:
# subprocessで dig +short を実行
result = subprocess.run(
["dig", "+short", domain, "A"],
capture_output=True,
text=True,
check=True,
)
# 改行で分割してリスト化(複数IPが返るケースを考慮)
resolved_ips = [
line.strip() for line in result.stdout.splitlines() if line.strip()
]
print(f"[{domain}] 解決されたIP: {resolved_ips}")
if expected_ip in resolved_ips:
print(f"--> SUCCESS: 期待通りのIP ({expected_ip}) が確認できました。")
return True
else:
print(
f"--> WARNING: 期待値 ({expected_ip}) と一致しません。キャッシュの残存を確認してください。"
)
return False
except subprocess.CalledProcessError as e:
print(f"ERROR: digコマンドの実行に失敗しました: {e}", file=sys.stderr)
return False
# 実行例
if __name__ == "__main__":
target_domain = "api.example.com"
expected = "192.0.2.1"
check_dns_resolution(target_domain, expected)
—
③ +nssearch:マスターネームサーバーの同期ズレを暴く
マルチクラウド環境や、プライマリー・セカンダリー構成のDNS(例: BINDとCloudflare、あるいは複数ベンダーの併用)を運用しているとき、「片方のサーバーだけレコードの更新が反映されていない」という同期ズレ(スプリットブレイン状態)が時折発生する。
これを一発で暴くのが +nssearch だ。
実際のコマンド例
dig +nssearch example.com
出力例と読み方
SOA ns1.example.com. hostmaster.example.com. 2023102701 10800 3600 604800 86400 from server 192.0.2.10 in 5 ms.
SOA ns2.example.com. hostmaster.example.com. 2023102700 10800 3600 604800 86400 from server 192.0.2.20 in 8 ms.
【シニアの眼】
出力結果の真ん中あたりにある数字(この例では 2023102701 と 2023102700)に注目してほしい。これはSOA(Start of Authority)レコードのシリアル番号(Serial Number)だ。
もし、管理している複数の権威ネームサーバーの間でこのシリアル番号が一致していない場合、セカンダリーへのゾーン転送(AXFR/IXFR)が失敗しているか、手動更新の同期漏れが起きている。
「あるユーザーからはアクセスできるのに、別のユーザーからはエラーになる」という、原因特定が最も難しい intermittent な障害の多くは、この +nssearch でシリアル番号の不一致を見つけることで秒速で解決できる。
—
3. トラブルシューティングの現場から:実務で使えるTips
最後に、現場で数々の障害を鎮火させてきた私から、若手エンジニアへ実践的なデバッグの手順を伝授しよう。
1. まずはクライアントのローカルキャッシュを疑うな、DNSリゾルバーを疑え
ユーザーから「繋がらない」と言われたら、まずは自分の手元だけでなく、障害が報告されているリージョンやクライアントが使っているDNSサーバー(Public DNSかキャリア網内か)を指定して dig @<DNSサーバーのIP> api.example.com を叩け。@ を使って特定のDNSサーバーに直接クエリを飛ばすテクニックは基本中の基本だ。
2. TTLのトラップに気をつけろ
「レコードを直したのに直らない」と嘆くエンジニアの9割は、TTL(Time To Live)の有効期限が切れる前に確認している、あるいは途中のプロキシやブラウザ、OSのキャッシュに阻まれている。dig で確認するときは必ず +noall +answer や +nocmd などの詳細表示を組み合わせ、返ってきたレスポンスに含まれるTTLの値(秒数)を確認し、それが枯渇するのを待つか、キャッシュをフラッシュ(systemd-resolve --flush-caches や nscd の再起動など)する勇気を持て。
—
まとめ
ネットワークトラブルの現場において、パケットは嘘をつかない。そして、DNSという巨大な分散システムの挙動を最も手軽に、かつ正確に手元でトレースできるのが dig コマンドのショートカットオプションたちだ。
+traceでルートから委譲先までのバトンリレーを可視化し、+shortでスクリプトやオートメーションに結果を流し込み、+nssearchで権威サーバー間のシリアル番号のズレを瞬時に暴く。
この3つの引き出しを持っているだけで、君が次回の障害対応で迷子になる確率は劇的に減るはずだ。さあ、コンソールを開き、自分の管理するドメインで試してみるといい。パケットの息吹が聞こえてくるはずだ。
コメント