【実務・中級編】 DHCPスヌーピング(DHCP Snooping)による不正DHCPサーバ対策とバインディングデータベース – インフラ・物理&L2/L3ネットワーク基礎実践ガイド

ネットワークの「信頼」をハックせよ:DHCPスヌーピングで守るL2の防壁

ネットワークエンジニアとして現場を歩いていると、たまに「なぜか知らないIPアドレスが降ってくる」「デフォルトゲートウェイがすり替わっている」という怪奇現象に遭遇することがある。犯人は大抵、誰かが不用意にデスクの下に設置した家庭用ルータのDHCP機能だ。

L2スイッチの世界では、MACアドレスを学習し、パケットを振り分けるのが基本だ。しかし、そこに「誰が正規のDHCPサーバか」という概念はない。これを放置するのは、オフィスのエントランスに誰でも入れる鍵を置いておくようなものだ。

今回は、このL2の脆弱性を突く不正DHCP攻撃を封じ込める「DHCPスヌーピング(DHCP Snooping)」の深淵を紐解いていこう。

—

DHCPスヌーピングの哲学:信頼と不信の境界線

DHCPスヌーピングは、スイッチのポートを「信頼できる(Trusted)」か「信頼できない(Untrusted)」に分類することで、ネットワークの秩序を保つセキュリティ機能だ。

  • Trustedポート: 正規のDHCPサーバが接続されているポート。すべてのDHCPメッセージ(DHCPOFFER, DHCPACK等)を通過させる。
  • Untrustedポート: 一般クライアントが接続するポート。ここからやってくるDHCPOFFERやDHCPACKは、即座にドロップされる。

この単純な仕組みが、不正なDHCPサーバによる「中間者攻撃(MITM)」を物理層に近い部分で防ぐ。

バインディングデータベースという「名簿」

DHCPスヌーピングを有効にすると、スイッチはスイッチングハブとしての役割を超え、DHCPのやり取りを「監視」し始める。

1. クライアントがDHCPDISCOVERを送る。
2. 正規のサーバがDHCPACKを返す。
3. スイッチはこの瞬間、MACアドレス、割り当てられたIP、リース時間、接続ポートを紐付けたバインディングデータベースを作成する。

このデータベースは、後の IP Source Guard や Dynamic ARP Inspection (DAI) といった高度なセキュリティ機能の「正当性の根拠」となる。いわば、ネットワーク界の入管チェックリストだ。

—

実践:Catalystスイッチでの設定例

現場でよく使われるCisco Catalyst(IOS)を例に挙げよう。設定は極めてシンプルだが、手順を飛ばすとネットワークが全滅するので注意が必要だ。

! 1. まずはグローバルで有効化
ip dhcp snooping
! 2. 対象のVLANで有効化
ip dhcp snooping vlan 10,20

! 3. アップリンク等の信頼できるポート設定
interface GigabitEthernet0/1
 description Uplink to DHCP Server
 ip dhcp snooping trust

! 4. クライアント用ポートはデフォルトでUntrustedなので設定不要だが、
!    レート制限をかけるのが運用の鉄則(DoS対策)
interface Range GigabitEthernet0/2 - 48
 ip dhcp snooping limit rate 100

ip dhcp snooping limit rate は非常に重要だ。これを設定しないと、悪意ある端末が大量の DHCPDISCOVER を送りつけ、CPUを枯渇させる「DHCP飢餓攻撃」を食らうことになる。

—

開発現場からの視点:IPアドレスの「正しさ」を検証する

インフラエンジニアとしては、DHCPスヌーピングが守っている世界を、アプリケーション側からも意識できると強い。たとえば、接続されているデバイスが正しいIPを持っているか確認する簡単なPythonスクリプトを考えてみよう。

import socket

def check_local_ip():
    """
    自端末のIPを取得して確認する。
    DHCPスヌーピングが効いている環境では、勝手なIPを付与すると
    ネットワークから排除されるため、このスクリプトが通信できなくなる。
    """
    hostname = socket.gethostname()
    ip_address = socket.gethostbyname(hostname)
    
    print(f"Current Host: {hostname}")
    print(f"Assigned IP: {ip_address}")
    
    # 実際にはここで、許可されたサブネット内か検証するロジックを組む
    if not ip_address.startswith("192.168.10."):
        print("警告: 許可されていないセグメントのIPです!")

if __name__ == "__main__":
    check_local_ip()

もし皆さんがAPIを設計する際、バックエンドで「クライアントのIP」を信頼して認証を行っているなら、そのIPがDHCPスヌーピングによって保護された「本物」であることを前提にできる。信頼の連鎖は、L2から始まるのだ。

—

トラブルシューティングの勘所

最後に、現場でこの機能を投入する際にハマるポイントを伝授する。

1. Option 82の罠: デフォルトではスイッチは DHCP relay agent information (Option 82) を付与する。サーバ側がこれに対応していないと、DHCPのやり取りが拒絶されることがある。不要なら no ip dhcp snooping information option を検討せよ。
2. データベースの保存先: スイッチの再起動でデータベースが消えると、全クライアントがIP再取得を求められ、ネットワークが一瞬フラップする。必ず ip dhcp snooping database flash:/dhcp_snooping.db のように外部メモリへ書き出す設定を忘れないこと。

ネットワークは「性悪説」で設計するのが大人の作法だ。DHCPスヌーピングは、そのための最も基本的かつ強力な武器である。ぜひ、明日の運用からこの「門番」を導入してみてほしい。

コメント

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