【実務・中級編】 DNSキャッシュポイズニングやスプーフィングのdigを用いた簡易検証 – トラブルシューティング&ネットワーク運用監視実践ガイド

DNSの「信頼」をハッキングする:digで紐解くトランザクションIDとポートのランダム性

ネットワークエンジニアとして深夜のデータセンターで冷気に当たりながらパケットキャプチャを眺めていると、時折「DNSって、なんでこんなに無防備なんだろう」と溜息をつきたくなる瞬間があります。

DNSキャッシュポイズニング。かつて世界を震撼させたこの攻撃は、単なる古臭い脆弱性の話ではありません。現代のクラウドネイティブな環境でも、名前解決の信頼性が揺らげば、APIの通信先が偽のサーバーにすり替わり、データ漏洩の入り口になります。今日は、このDNSの「脆弱性の防波堤」がいかに機能しているのか、digコマンドを片手に、泥臭い実務の視点から解説します。

—

なぜDNSは「当たる」のか:トランザクションIDとソースポートの役割

DNSの通信(UDP/53)は、コネクションレスです。クライアントが問いを投げ、サーバーが答える。この一対一のやり取りを成立させるために、DNSプロトコルは2つの「鍵」を使っています。

1. トランザクションID (Transaction ID): 16ビットの識別子。問い合わせと応答を紐付けるための「合い言葉」。
2. ソースポート (Source Port): クライアント側がランダムに割り当てるポート番号。

もし攻撃者が、あなたが送信した問い合わせに対する「偽の応答」を、正しい応答よりも先に送り届けることができれば、OSやDNSキャッシュサーバーはそれを「正当な回答」と見なしてキャッシュに保存してしまいます。これがキャッシュポイズニングの基本原理です。

これを防ぐための現代の鉄則は、「IDとポートをいかに予測不能にするか」に尽きます。

—

digで「予測可能性」を覗き見る

まずは、手元の環境でDNSサーバーがどの程度のランダム性を担保しているか、digを使って確認してみましょう。何度も問い合わせを投げて、ヘッダー情報を観察します。

# 繰り返しDNSクエリを投げ、出力結果からIDとポートを抽出する
for i in {1..5}; do
  # +stats オプションで詳細な通信統計を表示
  # grepでトランザクションID(id)を抽出
  dig @8.8.8.8 google.com +stats | grep "id"
done

実行結果を見ると、id: 12345 のような数字が毎回変わっているはずです。もしこのIDが固定値に近い挙動を示していたら、そのDNSサーバーは脆弱です。

重要なチェックポイント

  • トランザクションIDの乱数性: 16ビット(65,536通り)の空間が十分にシャッフルされているか。
  • ソースポートの固定化: 近年のセキュアな環境では、DNS問い合わせごとにソースポートもランダムに変動します(UDPポートのランダム化)。これを検証するには、tcpdumpを併用するのが現場の定石です。
# 別のターミナルでパケットをキャプチャしてポートを確認
sudo tcpdump -ni eth0 udp port 53

ここで表示される client_port > 53 の client_port が、問い合わせのたびに異なっているかを確認してください。もし常に固定ポート(例: 5353など)を使っているリゾルバがあれば、それは攻撃者にとって「格好の的」です。

—

API開発者が知るべき「名前解決の罠」

Web API開発では、curlや Python の requests ライブラリで外部サービスを叩くことが日常茶飯事ですが、ここでも「名前解決」の信頼性は重要です。

例えば、PythonでDNSの設定を意識したコードを書く場合、以下のような挙動を理解しておく必要があります。

import socket

# 特定のDNSサーバーを指定して名前解決を行う例(dnspythonライブラリ等を使用)
# 開発環境では、Google Public DNS (8.8.8.8) だけでなく、
# 自社の内部DNSの冗長性やセキュリティ設定を確認することが重要です。
try:
    # 接続先ホストのIPを解決
    ip = socket.gethostbyname('api.example.com')
    print(f"解決されたIP: {ip}")
except socket.gaierror:
    print("名前解決に失敗しました。DNSキャッシュが汚染されている可能性があります。")

API設計時には、「DNSの結果を過信しない」という防衛的アプローチも重要です。例えば、重要なAPI通信においては、信頼できる証明書(CA)を用いたTLS検証を徹底することで、万が一DNSがポイズニングされても、偽サーバーとのハンドシェイク時に証明書エラーで遮断することが可能です。

—

現場のシニアとしてのアドバイス:運用の勘所

最後に、現場で障害対応にあたる皆さんへ、いくつかのアドバイスを送ります。

  • DNSSECを検討せよ: 根本解決策はDNSSEC(DNS Security Extensions)です。デジタル署名によって応答の正当性を証明します。インフラ設計の要件に必ず含めるべきです。
  • キャッシュリゾルバの選定: 公共のDNSサーバーを使う場合、セキュリティ機能(DNS over HTTPS/TLSなど)が有効なものを選んでください。
  • 異常値に敏感になる: dig での応答時間が極端に速い、あるいは特定の時間帯だけパケットのドロップが目立つ場合、それは攻撃の予兆かもしれません。

DNSは、ネットワークの「電話帳」です。ここが書き換えられてしまえば、どれほど強固なファイアウォールも意味をなしません。dig コマンドでパケットの挙動を追うことは、まさにネットワークの「脈拍」を測るようなもの。ぜひ、コマンドを打つその指先で、パケットの動きを想像してみてください。

皆さんのインフラが、今日も安全に名前解決を行えることを願っています。それでは、現場からは以上です。

コメント

タイトルとURLをコピーしました