【実務・中級編】 悪性ドメイン解決を伴うDNSトラフィックとDGAの検知 – サイバーセキュリティとプライバシー保護実践ガイド

ランサムウェアの裏側を暴く:DGAトラフィックの正体とネットワークレイヤーでの泥臭い検知術

夜中の3時、突然鳴り響くインシデントアラート。
「社内端末から不審な外部へのDNSクエリが急増しています」

SOC(セキュリティオペレーションセンター)の画面を覗き込むと、そこには見たこともない文字列のドメイン名が、まるでマシンガンのように大量のフルリゾルバーへ叩きつけられていた。.bit、.top、あるいは誰も聞いたことのないトップレベルドメインに向けて、1秒間に数十件もの名前解決要求が飛んでいる。

「これだ……DGA(Domain Generation Algorithm)の波が来たんだ」

Web APIの設計やモダンなインフラ運用に没頭しているエンジニアの皆さん、こんにちは。私たちは普段、美しいJSONのやり取りや、コンテナのオーケストレーション、ミリ秒単位のレイテンシ削減に心を奪われがちです。しかし、どれほど洗練されたAPIを構築しようとも、その下を支えるネットワークの足元がすくわれれば、システムは一瞬でランサムウェアの餌食になります。

今回は、近年の高度なサイバー攻撃で常套手段となっている「悪性ドメイン解決を伴うDNSトラフィックとDGAの検知」について、ネットワークの泥臭い挙動と、現場で本当に使える実践的な防御・検知手法を徹底的に解説していきます。

—

1. DGA(Domain Generation Algorithm)とは何か?

ランサムウェアが端末を暗号化し、身代金を要求するためには、攻撃者の司令塔であるC2(Command and Control)サーバーと通信しなければなりません。

昔のマルウェアは、ハードコードされた固定のIPアドレスや、一つのドメイン名に接続していました。しかし、それではセキュリティチームがそのIPやドメインをブラックリスト(ファイアウォールやDNSフィルタ)に登録した瞬間、通信は完全に遮断されてしまいます。攻撃者たちもバカではありません。そこで生み出されたのが、「アルゴリズムによって動的に通信先を生成する」DGAです。

タイムスタンプとシード値が紡ぐ無限のドメイン

DGAを実装したマルウェアは、あらかじめ埋め込まれた「シード値」と、現在の日時(タイムスタンプ)などを組み合わせ、疑似乱数生成器(PRNG)を用いて、毎日数百から数千個のランダムなドメイン名を自動生成します。

例えば、以下のような文字列を見たことはないでしょうか?

  • q3j4h5g6f7d8s9a0.com
  • x8z7y6w5v4u3t2s1.net
  • akjdfh8734rfhkjs.org

これらは人間がキーボードを適当に叩いたのではなく、アルゴリズムが数学的に導き出した文字列です。マルウェアはこの大量の候補ドメインに対して次々とDNSクエリを投げ、たまたま攻撃者がその日のために事前登録していたドメイン(ヒットするドメイン)からの応答を待ち受けるのです。

この「大量の未解決DNSリクエスト(NXDOMAINの嵐)」こそが、ネットワークエンジニアが夜中に叩き起こされる、DGA検知の最大のシグナルとなります。

—

2. 標準仕様とDNSトラフィックの裏側

DNS(Domain Name System)は、RFC 1034およびRFC 1035で規定されたインターネットの根幹をなすプロトコルです。通常、クライアントはキャッシュサーバー(フルリゾルバー)に対して A レコードや AAAA レコードの問い合わせ(Query)を行います。

正常な通信とDGA通信の決定的な違い

正常なアプリケーション(例えばあなたが設計したWeb APIクライアント)であれば、接続先は固定のドメイン(例: api.example.com)であり、名前解決が成功すればそのIPアドレスに対して持続的なTCPコネクションやHTTP/2・HTTP/3のセッションを張ります。

一方、DGAが引き起こすDNSトラフィックの挙動は、パケットキャプチャ(PCAP)を覗くと一目瞭然です。

1. 高エントロピーな文字列の連打:
人間が読むことを想定していないため、文字のランダム性が高く、シャノンエントロピー(情報の不確実性を示す指標)の値が異常に高くなります。
2. 圧倒的な NXDOMAIN(Non-Existent Domain)率:
攻撃者が実際にその日登録しているドメインは全体のほんの一部です。そのため、DNSサーバーからの応答の多くは「そんなドメインは存在しません」という RCODE: 3 (NXDOMAIN) になります。
3. 異常なクエリ頻度:
数分から数時間の間に、単一のホストから何千もの異なるドメイン名に対するリクエストが集中します。

—

3. 実践:DGAトラフィックを検知・分析するコードと設定

では、実際にインフラ運用者やセキュリティエンジニアとして、この不審なトラフィックをどのように検知・分析すればよいのでしょうか。ここでは、Pythonを用いたログ解析のシミュレーションと、DNSサーバー(BINDやPowerDNS等)でのロギング設定の考え方を解説します。

パターンA: PythonによるDNSログのエントロピー分析スクリプト

実務では、DNSのクエリログ(BINDの query.log や、各ベンダーのSIEMに集約されたログ)から、ドメイン名のランダム性(エントロピー)を計算し、閾値を超えたものを検知するスクリプトを組み込むことが有効です。

以下のPythonスクリプトは、渡されたドメイン名の文字列からシャノンエントロピーを計算し、DGAの疑いがあるかを判定するロジックの実装例です。

import math
from collections import Counter

def calculate_shannon_entropy(text: str) -> float:
    """
    文字列のシャノンエントロピーを計算する。
    値が大きいほど、文字のランダム性(=DGAの可能性)が高いと判定できる。
    """
    if not text:
        return 0.0
    
    # 文字列の長さを取得
    length = len(text)
    # 各文字の出現回数をカウント
    char_counts = Counter(text)
    
    entropy = 0.0
    for count in char_counts.values():
        # 確率を計算
        probability = count / length
        # シャノンエントロピーの公式に代入: -sum(p * log2(p))
        entropy -= probability * math.log2(probability)
        
    return entropy

# テスト用のドメイン名リスト(正常なドメイン vs DGA疑い)
sample_domains = [
    "api-internal.example.com",  # 正常な社内APIドメイン
    "login.microsoftonline.com",  # 正常なSaaSドメイン
    "q3j4h5g6f7d8s9a0.com",       # 明らかにランダムなDGA疑い
    "akjdfh8734rfhkjs.org"        # 明らかにランダムなDGA疑い
]

# 判定閾値(経験則として、ドメイン名部分のエントロピーが4.0を超えると怪しい)
ENTROPY_THRESHOLD = 4.0

print("--- DGA検知エントロピー分析シミュレーション ---")
for domain in sample_domains:
    # サブドメインやルートドメインを簡易的に分割して評価
    subdomain = domain.split('.')[0]
    entropy = calculate_shannon_entropy(subdomain)
    
    is_suspicious = entropy > ENTROPY_THRESHOLD
    status = "[警告: DGAの可能性]" if is_suspicious else "[正常]"
    
    print(f"Domain: {domain:30} | Entropy: {entropy:.2f} | Status: {status}")

このスクリプトをSplunkやElasticsearch(Logstash)のパイプライン、あるいはAWS Lambda(CloudWatch Logsトリガー)に組み込むことで、リアルタイムに近い形で異常なドメイン解決要求をキャッチできます。

パターンB: BIND 9 などのDNSキャッシュサーバーでのロギング・レートリミット設定

ネットワークの最前線であるフルリゾルバー(DNSキャッシュサーバー)側でも、防衛線を張る必要があります。不審な端末が大量のドメイン解決を試みる際、キャッシュサーバー自体がリソース枯渇(DoS状態)に陥るのを防ぐため、Response Rate Limiting (RRL) や、異常なクエリパターンの監視設定が重要になります。

例えば、BIND 9 (named.conf) において、不正なリクエストや過剰なトラフィックに対する基本的なセキュリティ配慮を含めた設定の考え方は以下の通りです。

options {
    directory "/var/named";
    
    // 再帰問い合わせ(Recursion)を許可する範囲を社内ネットワークに厳格に絞る
    // これにより外部からの踏み台(オープンリゾルバー化)を防ぐ
    allow-recursion { 
        192.168.10.0/24; 
        10.100.0.0/16; 
        localhost; 
    };

    // レートリミットの設定(DDoSやDGAによるリゾルバーの負荷軽減)
    // 同一ソースからの過剰な応答に対してスロットリングを行う
    rate-limit {
        responses-per-second 10;
        window 5;
    };

    // クエリログを詳細に出力し、外部のSIEMやログ収集基盤(Fluentd等)へ転送する
    querylog yes;
};

logging {
    channel query_log {
        file "logs/query.log" versions 3 size 50m;
        severity info;
        print-time yes;
    };
    category queries { query_log; };
};

現場のインフラエンジニアとしては、単にログを取るだけでなく、この query.log の中に NXDOMAIN が異常な頻度で頻発していないか、特定の IPアドレス(192.168.10.X など) からのクエリばかりになっていないかを監視基盤(Prometheus + Grafana など)で可視化しておくことが、夜の平穏を守る鍵となります。

—

4. 現場で役立つトラブルシューティングとTips

最後に、実際にインシデント対応やフォレンジックを行う際に、シニアエンジニアとして知っておくべき実務的なTipsをいくつか授けましょう。

1. パケットキャプチャには tshark や tcpdump を活用せよ
GUIのツールが開けないリモートのLinuxサーバー環境では、以下のコマンドで怪しいDNSトラフィックを瞬時にあぶり出せます。

# ポート53(DNS)のトラフィックをキャプチャし、NXDOMAIN応答の割合や頻出ソースIPを調査
   sudo tcpdump -nn -i eth0 port 53 -c 1000

2. EDR(Endpoint Detection and Response)との相関分析
ネットワーク層だけでDGAを完全に見抜くのは、アルゴリズムの巧妙化(静的から動的なものへの移行)に伴い困難になっています。「どのプロセスがそのDNSクエリを発行したのか」を特定するためには、DNSログとEDR(Microsoft Defender for EndpointやCrowdStrikeなど)のプロセス起動ログを突き合わせる相関分析が不可欠です。nslookup.exe や怪しいスクリプト実行ファイルがバックグラウンドで動いていないか必ず確認してください。
3. DNSシンクホールの活用
万が一、DGAドメインの一部が実際に悪意ある攻撃者に登録されてしまった場合、ファイアウォールで遮断するだけでなく、社内のDNSサーバーでそのドメイン群を自社の安全なローカルIP(シンクホールサーバー)へ向き先を偽装(スプーフ)することで、感染端末のIPアドレスを特定し、迅速に隔離措置を取ることができます。

—

まとめ

DGAを用いたランサムウェアのC2通信は、もはや特殊なサイバー攻撃ではなく、いつ自社のネットワークが標的になってもおかしくない身近な脅威です。

Web APIの設計やインフラの自動化に携わる私たちエンジニアであっても、「アプリケーション層の下には強固なネットワークとDNSという名前解決の基盤がある」という意識を忘れてはなりません。エントロピー分析やログの常時監視、適切なレートリミットといった地道な泥臭い対策こそが、企業の命運を分ける防壁となります。

さあ、アラートの波が押し寄せる前に、今一度自社のDNSログとネットワークの足元を見直してみませんか?

コメント

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