問題の背景:なぜレイヤー2ネットワークはスプーフィングの被害を受けるのか
従来のレイヤー2ネットワークは、回線上のすべてのホストが信頼できることを前提に動作しています。サーバーがローカルサブネット上のIPと通信する必要がある場合、Address Resolution Protocol(ARP)クエリをブロードキャストして「このIPを保持しているのは誰か?」と問い合わせます。IPの所有者が自身のMedia Access Control(MAC)アドレスを応答し、両方のホストがそれぞれのローカルARPキャッシュを更新します。
標準的なARPには認証機能が一切ありません。不正なマシン、侵害されたコンテナ、または不正なVMであっても、要求されていないGratuitous ARP(GARP)応答を自由に送信できます。これにより、デフォルトゲートウェイ、データベースノード、またはコアDNSリゾルバのIPを偽称することが可能です。標的となったホストは検証なしにキャッシュテーブルを上書きしてしまいます。その結果、トラフィックは即座に攻撃者を経由してルーティングされ、パケットの傍受や改ざん、あるいはサイレントなパケット破棄(ブラックホール化)が可能になります。
この問題は単なる理論上のものではありません。昨年、私たちのチームはステージング環境のKubernetesクラスタで発生した断続的な502エラーとTLSハンドシェイクの切断の原因究明に3時間を費やしました。原因は、デフォルトゲートウェイのIP(10.0.10.1)と自身のMACアドレスをペアにして継続的にブロードキャストするアグレッシブなロードバランサースクリプトを実行していた、設定ミスのあるテスト用VMでした。40台以上のワーカーノードが数分以内にキャッシュを汚染されてしまったのです。
コアコンセプト:パッシブ監視 vs スイッチによるアクティブ制御
ARPポイズニングを阻止するには、ホストレベルでの検知とスイッチレベルでのハードウェア制御という、相互に補完し合う2つの防御レイヤーが必要です。
1. ARPキャッシュポイズニングの仕組み
OSはパケットごとにブロードキャストドメインへ問い合わせるのを避けるため、メモリ上にARPテーブルを保持しています。ホストA(10.0.10.25)がゲートウェイ10.0.10.1にアクセスしたいと仮定します。攻撃者が10.0.10.1 is at aa:bb:cc:11:22:33と主張する偽造パケットを送信すると、ホストAはそのフレームを受け入れ、検証することなくARPテーブルを更新します。以降、ホストAからのすべての送信トラフィックは攻撃者へ直接ルーティングされるようになります。
2. Arpwatchによるパッシブ検知
Arpwatchは、レイヤー2のブロードキャストアクティビティを監視する軽量なLinuxデーモンです。IPとMACアドレスのペアリングを時系列でマッピングし、IPが新しいMACアドレスに関連付けられたり、インターフェース間を移動したり、未登録のベンダーOUIが導入されたりした際に、syslogへの記録やメール通知によって異常を知らせます。
3. Dynamic ARP Inspection(DAI)によるアクティブ防御
Arpwatchはインシデント発生後にアラートを発行しますが、悪意のあるフレームを破棄することはできません。そこで登場するのがDynamic ARP Inspection(DAI)です。DAIはマネージドスイッチのハードウェア機能であり、信頼されていない(untrusted)アクセスポート上のARPリクエストおよびリプライをインターセプトし、各フレームをスイッチのDHCP Snoopingバインディングデータベースと照合します。IPとMACアドレスのペアが有効なリース情報と一致しない場合、スイッチのASICはそのフレームを即座に破棄します。
実践演習:ArpwatchとスイッチレベルDAIの導入手順
具体的な実装手順を以下に示します。まずUbuntu監視ノードでパッシブアラートを設定し、続いてスイッチのアクセスポートを保護します。
ステップ1:LinuxへのArpwatchのインストールと設定
管理ホストまたは専用のネットワークプローブにパッケージをインストールします:
sudo apt update
sudo apt install -y arpwatch
ip link showで監視対象のインターフェースを確認し、サービスのデフォルト設定ファイルを編集します:
sudo nano /etc/default/arpwatch
リスニングインターフェースと通知の送信先を指定します:
# /etc/default/arpwatch
INTERFACES="eth0"
ARGS="-N -m [email protected] -R 6"
状態ファイルを初期化し、デーモンを起動します:
# 追跡データベースを初期化
sudo touch /var/lib/arpwatch/arp.dat
sudo chown -R arpwatch:arpwatch /var/lib/arpwatch
# サービスを起動
sudo systemctl enable --now arpwatch
sudo systemctl status arpwatch
システムジャーナルでリアルタイムの検知状況を確認します:
sudo journalctl -u arpwatch -f
アドレスの競合が発生すると、Arpwatchは構造化されたアラートをログに出力します:
arpwatch: changed ethernet address: 10.0.10.1 00:50:56:a1:2b:3c (old 00:0c:29:4f:8e:12)
ステップ2:アクセススイッチでDHCP Snoopingを有効化
DAIは動的なIP割り当てを検証するためにDHCP Snoopingデータベースを使用します。スイッチ(Cisco IOS構文)でSnoopingをグローバルに有効化し、ユーザー/サーバー用VLAN(例:VLAN 10)に関連付けます:
Switch# configure terminal
Switch(config)# ip dhcp snooping
Switch(config)# ip dhcp snooping vlan 10
Switch(config)# no ip dhcp snooping information option
アップリンクポートを信頼(trusted)モードに設定し、正当なDHCPサーバーからのOfferパケットを許可します:
Switch(config)# interface GigabitEthernet0/1
Switch(config-if)# description Core-Router-Uplink
Switch(config-if)# ip dhcp snooping trust
Switch(config-if)# exit
ステップ3:Dynamic ARP Inspection(DAI)の有効化
Snoopingが有効になったら、VLAN 10でDAIを有効化し、厳格なペイロード検証を有効にします:
Switch(config)# ip arp inspection vlan 10
Switch(config)# ip arp inspection validate src-mac dst-mac ip
アップリンクインターフェースを信頼設定にし、トランク経由での正当なルーターARPリプライを許可します:
Switch(config)# interface GigabitEthernet0/1
Switch(config-if)# ip arp inspection trust
Switch(config-if)# exit
信頼されていないアクセスポートにレート制限を適用します。これにより、攻撃者がARPフラッド攻撃によってスイッチのCPUリソースを枯渇させるのを防ぎます:
Switch(config)# interface range GigabitEthernet0/2 - 24
Switch(config-if-range)# ip arp inspection limit rate 15
Switch(config-if-range)# exit
ステップ4:ARPアクセスリストによる静的IPホストの許可
静的IPアドレスが設定されたサーバーはDHCPリクエストを送信しないため、DHCP Snoopingエントリーが存在しません。例外設定を行わない場合、DAIによってそれらの正当なトラフィックが破棄されてしまいます。これらのエンドポイント用にARPアクセスリストを定義します:
Switch(config)# arp access-list STATIC-SERVERS
Switch(config-arp-nacl)# permit ip host 10.0.10.10 mac host 0050.56a1.2b3c
Switch(config-arp-nacl)# permit ip host 10.0.10.11 mac host 0050.56a1.4d5e
Switch(config-arp-nacl)# exit
Switch(config)# ip arp inspection filter STATIC-SERVERS vlan 10 static
ステップ5:バインディングの確認と破棄カウンターの確認
スイッチにリース情報が登録されていることを確認します:
Switch# show ip dhcp snooping binding
DAIのパケット破棄統計を確認し、保護が機能していることを確認します:
Switch# show ip arp inspection vlan 10
Source Mac Validation : Enabled
Destination Mac Validation : Enabled
IP Transition Validation : Enabled
Vlan 10 Configuration
---------------------
Verify Source MAC : Enabled
Verify Destination MAC : Enabled
Verify IP : Enabled
Vlan 10 Statistics
------------------
Forwarded : 128450
Dropped : 23
DHCP Drops : 23
ACL Drops : 0
まとめ
Arpwatchを使用すると、Linuxサブネット全体の可視性をホストレベルで迅速に確保できます。しかし、本格的なレイヤー2の防御にはハードウェアレベルでの強制制御が不可欠です。スイッチ上でDHCP SnoopingとDynamic ARP Inspectionを組み合わせることで、物理ポートレベルでARPポイズニングの試みを阻止し、ゲートウェイやサーバーを中間者(Man-in-the-Middle)攻撃から守ることができます。

