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 コマンドでパケットの挙動を追うことは、まさにネットワークの「脈拍」を測るようなもの。ぜひ、コマンドを打つその指先で、パケットの動きを想像してみてください。
皆さんのインフラが、今日も安全に名前解決を行えることを願っています。それでは、現場からは以上です。
コメント