
WindowsのDNSトラフィックをpktmon経由で監視し、ポイズニング、スプーフィング、不正なリゾルバ応答、ゲートウェイMACアドレスの変更を検出してアラートを記録するPowerShellスクリプトです。
Windowsマシン自身のネットワークトラフィックを監視し、DNSポイズニング / スプーフィングの兆候を検出する単一ファイルのPowerShellスクリプトです。Windows 10 (1809以降)、Windows 11、Windows Server 2019以降に標準搭載されているパケットキャプチャツール pktmon を使用します。サードパーティ製のキャプチャツール(Wireshark、Npcap、tcpdump)は不要です。
OSのネットワークスタックでDNSトラフィック(UDP/TCPポート53)をキャプチャします。これにより一般的なマシン上のLANおよびWANトラフィックの両方をカバーし、生のパケットを自身で解析します — pcapngバイナリ形式、Ethernet/IP/UDP/TCPヘッダー、そしてDNSメッセージ形式(名前圧縮ポインタを含む)を、すべてネイティブPowerShellのみで処理します。
macOSとLinuxをカバーする姉妹版のbash/tcpdumpバージョンもあります。
| シグナル | 重要な理由 |
|---|---|
| 同一DNSクエリに対する矛盾する応答 | ポイズニング攻撃の典型的なシグネチャ:攻撃者が偽造した応答を本物の応答と競わせ、偽造応答が先に到着してキャッシュされることを狙います。 |
| 設定していないDNSサーバーからの応答 | Get-DnsClientServerAddress と比較します。認識されないサーバーからの応答は、オフパス攻撃者が応答を注入している可能性を示します。 |
| 未処理のクエリに対応しない応答 | モニターが問い合わせを確認していない質問への応答 — 注入/スプーフィングされたトラフィックの可能性があります(誤検知を避けるための起動時猶予期間付き)。 |
| セッション中にデフォルトゲートウェイのMACアドレスが変化 | 各キャプチャサイクルで Get-NetNeighbor を介してポーリングします。ARPスプーフィングは、攻撃者がLAN上のDNS改ざんを行うために最初に取る通常の手口です。 |
すべてのアラートは2つの部分を出力します:
[TECHNICAL] — 生のパケット詳細。さらに調査したい人向け[WHAT THIS MEANS] — なぜ重要かを平易な言葉で説明すべての出力はタイムスタンプ付きのログファイルにも書き込まれます。
pktmon.exe が利用可能であること(これらすべてに標準搭載)pktmon pcapng(解析用にキャプチャを変換するために使用)は初期の1809リリース後に追加されました。存在しない場合はWindowsを更新してくださいgit clone https://github.com/microlaser/dns-watchdog.git
cd dns-watchdog\windows
インストールするモジュールや外部依存関係はありません — スクリプト本体のみです。
昇格した(管理者) PowerShellから:
.\dns_watchdog.ps1
デフォルトでは、スクリプトはデフォルトゲートウェイと設定済みDNSサーバーを自動検出し、すべてのネットワークアダプターにわたってキャプチャします(pktmonはOSのネットワークスタックで動作するため、特定のアダプターを選択することなく、自然にLANとWANの両方のトラフィックをカバーします)。監視を停止するには Ctrl+C を押します。終了時にセッションのサマリーが表示されます。
.\dns_watchdog.ps1 [-LogFile <path>] [-CaptureIntervalSeconds <n>] [-GraceResponses <n>] [-KeepCaptures]
| パラメータ | 説明 |
|---|---|
-LogFile | セッションログのパス(デフォルト:.\dns_watchdog_<timestamp>.log) |
-CaptureIntervalSeconds | 変換・解析前の各キャプチャウィンドウの長さ。小さいほど検出遅延が減り、オーバーヘッドが増えます。デフォルト:5 |
-GraceResponses | 「一致するクエリなし」アラートが有効になる前に観察する応答数。起動時のノイズを避けるためです。デフォルト:10 |
-KeepCaptures | 解析後に削除する代わりに、各ウィンドウの .etl/.pcapng ファイルをディスクに保持します |
=========================================================================
DNS Watchdog (Windows) - DNS poisoning / spoofing monitor
=========================================================================
Capturing on: all network adapters (pktmon captures at the OS networking stack,
which covers this host's LAN and WAN traffic together)
Default gateway: 192.168.1.1 (MAC baseline: 60-95-F8-2B-5E-78)
Configured DNS: 192.168.0.1, 192.168.1.1
Log file: .\dns_watchdog_20260918_204725.log
...
[20:47:44.872] [ALERT] Conflicting DNS responses for the same query
[TECHNICAL] txn=64878 query=example.com (type 28) first_response=[AAAA:2607:f8b0:...] conflicting_response(src=10.0.0.9)=[AAAA:dead:beef::1]
[WHAT THIS MEANS] This machine's DNS question got two DIFFERENT answers back. Legitimate DNS servers don't normally do this. This is the textbook signature of a DNS poisoning attempt, where an attacker races a forged answer against the real one, hoping the forged one arrives first and gets cached.
Windowsには tcpdump をテキストパーサーにパイプする直接的な類似手段がありません — pktmon のライブコンソール出力は生のバイト列であり、デコードされた行ではありません。そのため、このスクリプトは代わりに次のことを行います:
pktmon を短いローテーションウィンドウ(デフォルト5秒)で実行し、.etl にキャプチャ.pcapng に変換(pktmon pcapng)知っておく価値のある癖: Windowsは、一部のスタックチェックポイントでEthernetヘッダーが追加される前に、ローカル生成(送信)パケットをキャプチャすることがよくあります。そのため、送信DNSクエリはリンク層フレーミングのない裸のIPパケットとして到着することがあり、一方、受信応答はワイヤーから完全にEthernetフレーミングされた状態で到着します。パーサーは両方を検出して処理します。また、pktmon は同じ物理パケットを複数回報告する傾向があります(ネットワークスタック内の複数のポイントでキャプチャされるため)。スクリプトは各キャプチャウィンドウ内でバイト単位で同一の繰り返しを重複排除し、1つの実パケットに対して複数回アラートが出ないようにします — 真に競合する/ポイズニングされた応答は内容が異なるため、この重複排除の影響を受けることはありません。
pktmon pcapng 変換にはある程度新しいWindowsビルドが必要です。非常に古い1809時代のシステムでは、代わりに pktmon etl2txt にフォールバックする必要があるかもしれません(ここでは実装されていません)。MIT(または好みに合わせて更新してください)。