「会議室で誰かが持ち込んだルータを繋いだら、社内PCが知らないIPを掴んで通信できなくなった」——これ、ネットワーク現場では今も普通に起きるトラブルです。原因のほとんどは不正DHCPサーバー。対策はシンプルで、CiscoスイッチならDHCPスヌーピングを1回ちゃんと入れれば99%の事故は防げます。

この記事では、Catalyst 2960-Xと9300で私が現場投入している設定手順、確認コマンド、よくあるハマりどころ、そしてDAI(Dynamic ARP Inspection)との連携までをまとめました。「とりあえずコマンドだけ知りたい」方は目次から該当の章まで飛んでもらってOKです。

Cisco DHCPスヌーピング構成図。コアスイッチ・アクセススイッチ・正規DHCPサーバー・不正DHCPサーバーを含むTrust/Untrustポート設計の全体像
DHCPスヌーピングを有効化したL2/L3構成例。正規サーバーへの経路だけがtrust、それ以外はuntrustで統一する。

DHCPスヌーピングとは何か、何を守るのか

DHCPスヌーピング(DHCP Snooping)は、スイッチがDHCPパケットの中身を覗き見しつつフィルタする機能です。といっても難しい話ではなくて、要は「このポートから出てくるDHCP Offerは無視する」というルールを、スイッチがポート単位でかける仕組み。

不正DHCPサーバーが引き起こす現場の事故

過去に遭遇した例を3つ挙げておきます。

  • 無線APの設定ミスで、LAN側に勝手にDHCPが立ってしまった
  • 開発部の検証用ルータ(YAMAHA RTX)を会議室LANに繋いでしまい、Offerをバラまいた
  • ウイルス感染したノートPCが不正なDHCPサーバーとして振る舞っていた(これは結構レア)

いずれも「端末がデフォゲを掴めない」「社内リソースに名前解決できない」という形で表面化します。ちなみに原因究明には平均で2〜3時間吸われる。個人的に、DHCPスヌーピングを入れていないネットワークを引き継いだら最初にやる設定、これです。

スヌーピングが守ってくれる仕組み

ざっくり書くとこう。

  1. スイッチ上でVLAN単位にスヌーピングを有効化する
  2. 各ポートをtrustuntrustに分ける
  3. untrustポートから入ってきたOffer/Ack/NAKなどサーバー発のメッセージは即ドロップ
  4. trustポート経由のDHCPだけ正規として扱い、バインディングテーブルを作る

このバインディングテーブル(MAC / IP / VLAN / ポート / リース時間)が後でDAIやIP Source Guardの根拠データになります。ここがこの機能の美味しいところ。

検証環境と構成(今回の前提)

記事中のコマンドは以下で動作確認しました。

  • コアSW:Catalyst 9300 / IOS XE 17.9.4a
  • アクセスSW:Catalyst 2960-X / IOS 15.2(7)E9
  • DHCPサーバー:Windows Server 2022(192.168.10.10)
  • VLAN:10(ユーザーセグメント、192.168.10.0/24)

構成図は冒頭に貼ったとおり。正規DHCPサーバーはコアSW配下に置き、各アクセスSWのアップリンクだけtrust、配下のクライアントポートは全部untrustにします。ここの設計をミスると後で痛い目を見ます(後述)。

CiscoスイッチでのDHCPスヌーピング設定手順

グローバルでスヌーピングを有効化

Switch(config)# ip dhcp snooping
Switch(config)# ip dhcp snooping vlan 10
Switch(config)# no ip dhcp snooping information option

1行目がスヌーピング自体の有効化、2行目で対象VLANを指定。3行目のno ip dhcp snooping information optionOption 82の付与を止めるオプションで、これを入れないとWindows DHCPサーバーがOption 82付きのDiscoverを理解できず、Offerを返さないケースがあります。実際、以前の案件でこれ忘れてて「設定はバッチリのはずなのにIPが降りない…」と1時間くらい悩みました。

ちなみにDHCPサーバー側でOption 82を理解できる構成(ISCのdhcpdとか、Ciscoルータのipdhcpプール)なら、むしろOption 82は有効化したほうが不正対策になる。環境次第です。

Trustポートの設定(DHCPサーバー方向のみ)

Switch(config)# interface GigabitEthernet1/0/1
Switch(config-if)# description ** uplink to Core / DHCP-server path **
Switch(config-if)# ip dhcp snooping trust

trustにするのは「正規DHCPサーバーに到達するポート」だけです。アップリンク=trust、アクセスポート=untrustと割り切ってください。

よくある間違い:「L2スイッチ同士を接続しているトランクを片側だけtrustにする」。これをやるとOfferが途中でドロップされる瞬間が発生して、クライアントによっては取得できたりできなかったりという非再現性トラブルになります。トランクはどっち側も trust で揃えるのが鉄則。

Rate-limit(レート制限)の設定

Switch(config)# interface range GigabitEthernet1/0/2 - 48
Switch(config-if-range)# ip dhcp snooping limit rate 15

untrustポート側でDiscover/Requestが大量に飛んでくるのを抑止する設定です。目安は15〜20pps。これ以上に設定するとスヌーピングのCPUリソースを食いつぶしかねないので、Cisco公式ドキュメントでも控えめな値が推奨されています。

一方でtrustポートにrate limitをかけると、リース更新集中時にOfferがドロップされる事故が起きるので、trust側にはかけないこと。ここ試験にも出そうな引っ掛けポイント。

バインディングDBの永続化

Switch(config)# ip dhcp snooping database flash:/dhcp-snoop.db
Switch(config)# ip dhcp snooping database write-delay 30

リブート後にバインディング情報を失わないためにflashに書いておく設定。write-delayは30秒が無難(短すぎるとフラッシュの書き込み寿命を縮める、長すぎると直近のリースが拾えない)。

動作確認コマンドと読み方

スヌーピングの状態を確認

Switch# show ip dhcp snooping
Switch DHCP snooping is enabled
Switch DHCP gleaning is disabled
DHCP snooping is configured on following VLANs:
10
DHCP snooping is operational on following VLANs:
10
Insertion of option 82 is disabled
   circuit-id default format: vlan-mod-port
   remote-id:    f4:4e:05:c1:a2:03 (MAC)
Option 82 on untrusted port is not allowed
Verification of hwaddr field is enabled
Verification of giaddr field is enabled
DHCP snooping trust/rate is configured on the following Interfaces:

Interface              Trusted    Allow option    Rate limit (pps)
-----------------------  -------    ------------    ----------------
GigabitEthernet1/0/1     yes        yes             unlimited
GigabitEthernet1/0/2     no         no              15

「operational on following VLANs」にちゃんと対象VLANが出ているかが最重要。ここが空欄のままならスヌーピングは設定だけ入っていて動いていない状態です。

バインディングテーブルを見る

Switch# show ip dhcp snooping binding
MacAddress          IpAddress        Lease(sec)  Type           VLAN  Interface
------------------  ---------------  ----------  -------------  ----  -----------------
00:1A:2B:3C:4D:5E   192.168.10.101   86072       dhcp-snooping  10    GigabitEthernet1/0/5
00:1A:2B:3C:4D:5F   192.168.10.102   85312       dhcp-snooping  10    GigabitEthernet1/0/7

これがスヌーピングDBの中身。MACとIPとポートが紐付いているのが分かります。この情報がDAIの検証基盤になる、というのが後で効いてきます。

不正Offerがドロップされた証拠を見る

Switch# show ip dhcp snooping statistics
   Packets Processed by DHCP Snooping                  = 24572
   Packets Dropped Because
     IDB not known                                     = 0
     Queue full                                        = 0
     Interface is in errdisabled                       = 0
     Rate limit exceeded                               = 0
     Received on untrusted ports                       = 17
     Nonzero giaddr                                    = 0
     Source mac not equal to chaddr                    = 0
     Binding mismatch                                  = 0
     Invalid opcode                                    = 0
     Invalid DHCP message type                         = 0

「Received on untrusted ports」がゼロでなければ、どこかで不正DHCPがOfferを出しています。この値が上がり続けているポートをdebugで掘ると犯人が見つかる。

現場でハマった実例:深夜メンテで地獄を見た話

深夜のL2SW更改案件で、旧機からコンフィグを移植したあと、翌朝「会議室のPCがネットに繋がらない」とヘルプデスク宛に10件以上の問い合わせが入ったことがあります。結論から言うと、アップリンク側のポートチャネル(Po1)にtrustを入れ忘れていたのが原因でした。

具体的にはこう:

  • 物理ポート(Gi1/0/1, Gi1/0/2)にはtrust設定済み
  • しかしPo1には設定が入っておらず、スヌーピング的には「untrust束ねたもの」として扱われていた
  • 結果、正規DHCPのOfferがドロップされ、会議室のDHCPリクエストだけが運悪く当たった

正解は、物理ポートではなくチャネルグループ(Port-channel)側にtrustを入れること。

Switch(config)# interface Port-channel1
Switch(config-if)# ip dhcp snooping trust

ポートチャネルやるときは、メンバーポート側の設定はチャネル側に吸い上げられるので、親インターフェースに入れる。これ、マニュアルをちゃんと読めば書いてあるんですが、徹夜作業ではマニュアルなんて読まないんですよ……。

DAI(Dynamic ARP Inspection)との連携

DHCPスヌーピングだけでも十分強力ですが、ARPスプーフィングまで塞ぎたいならDAIとセットで運用するのがおすすめ。むしろ、スヌーピングを入れた時点でDAIの準備は8割終わっています。

Switch(config)# ip arp inspection vlan 10
Switch(config)# interface GigabitEthernet1/0/1
Switch(config-if)# ip arp inspection trust

DAIは「ARPパケットのSender MAC/Sender IPの組み合わせがスヌーピングDBと一致しているか」をチェックする機能。スヌーピングDBに該当エントリがなければARPパケット自体を破棄します。

ここでよくあるミスが固定IP端末(サーバー等)の扱い。DHCPを使わない機器はスヌーピングDBに載らないので、DAIが有効だとARPごとドロップされます。対策はarp access-listで静的に許可するか、該当ポートをDAI trustにする。

Switch(config)# arp access-list STATIC-ARP
Switch(config-arp-nacl)# permit ip host 192.168.10.10 mac host 0011.2233.4455
Switch(config)# ip arp inspection filter STATIC-ARP vlan 10

検証用の仮想マシンとか、プリンタとか、DHCPを使わない機器がそこそこ居ると、このarp access-list管理がだんだん辛くなってくる。運用コスト考えると、可能な限り固定IP機器にもDHCP予約を使う設計にした方が楽です。

この方法のデメリット・注意点

正直、万能ではないです。運用してみて感じている弱点を正直に書いておきます。

  • スタックスイッチのMaster切替時に、バインディングDBの同期が追いつかないと一瞬ARPがドロップする瞬間がある
  • 古いCatalyst 2960(非-X、非-S)ではrate limitの上限が甘く、CPU負荷が上がりやすい
  • 無線LAN配下のローミング時、同一端末が別スイッチ配下に移動するとDBの同期遅延で数秒通信断することがある

特にスタックスイッチ絡みは、2024年以降のIOS XEでだいぶ改善されてますが、それでもHAフェイルオーバー時の振る舞いは自分の環境で一度は検証したほうがいい。この部分は「絶対安心です」と言い切るには私自身の検証がまだ足りないので、分かり次第追記するつもりです。

まとめ

DHCPスヌーピングを入れる理由は突き詰めると3つ。

  1. 不正DHCPサーバー起因の通信不良を物理的に潰せる
  2. MAC/IP/ポートのバインディングDBができるので、後からIP Source GuardやDAIが載せやすい
  3. 「誰がどのIPを使っているか」の追跡がshow一発で済むので、障害対応時間が縮む

個人的には、ユーザーセグメントが存在する全アクセスSWで標準実装にすべき機能だと思っています。設定ミスで事故ったとしても、untrust側にtrustを足す方向で復旧できるので、ロールバックもしやすい。

次に読むなら、同じくL2セキュリティ機能の「MACアドレステーブル確認とトラブルシューティング」あたりを合わせて読んでおくとL2セキュリティ全体像が見えやすいはずです。