「VLAN 10は通るのに、なぜかVLAN 20だけpingが返ってこない」——Trunkポート絡みのトラブルで、これほど多いパターンもない。設定は一見正しく見えるし、リンクは Up している。でも特定VLANだけが沈黙する。原因はだいたい3つに絞れる。
この記事では、現場で何度もハマったTrunkポートの「特定VLANだけ通信不能」問題を、原因の切り分け順に整理した。allowed vlanの設定漏れ、Native VLAN不一致、DTPの暴走——どれもCatalystの実機で再現しながら確認しているので、コマンドの出力例まで含めて使ってもらえる内容にしてある。
原因はほぼこの3つに集約される
経験上、Trunkポートで「一部のVLANだけ」疎通できないとき、原因の99%は次の3パターンに収まる。残り1%は配線やSFPの相性みたいな物理層の闇なので、まずは設定を疑うのが早い。
| 原因パターン | 症状 | 最初に打つコマンド |
|---|---|---|
| allowed vlanの設定漏れ | 対象VLANのフレームがTrunk上で破棄。両端で対称に発生 | show interfaces trunk |
| Native VLAN不一致 | タグ無しフレーム(Native扱いVLAN)だけ通信不能。CDPに警告 | show cdp neighbors detail |
| DTPでaccess化 | Trunkのつもりが片側がAccessに。1つのVLANだけ通る | show interfaces switchport |
以前、客先の機器入れ替え案件で、新しいCatalyst 9300に旧構成のVLANを移行したとき、VLAN 10と30は問題なく通るのにVLAN 20だけ全く通信できない事象に遭遇した。深夜2時、メンテ枠は朝6時まで。汗だくで show interfaces trunk を打ったら、Allowed VLANs列に「1,10,30」とだけ書かれていて、20が抜けていた。前任者がコピペで設定を流したときに範囲指定をミスしたらしい。allowed vlanは add を付けないと上書きされるので、ここを知らないと確実にやらかす。
切り分けの前にこれだけは見ておく
細かい話に入る前に、両端のスイッチで以下を一通り確認する。ここが揃ってない状態でdebug回しても、ノイズが多くて時間の無駄になりがち。
| 確認項目 | 確認コマンド | 期待する状態 |
|---|---|---|
| VLAN存在 | show vlan brief | 対象VLANがactive |
| Trunk動作モード | show interfaces switchport | Mode: trunk |
| 許可VLAN一覧 | show interfaces trunk | Allowed/Active両方に対象VLAN |
| Native VLAN | show interfaces trunk | 両端で同じID |
| カプセル化 | show interfaces switchport | 802.1Q(dot1q) |
| 物理リンク | show interfaces status | connected, trunk |
show interfaces trunk の出力には「Vlans allowed on trunk」「Vlans allowed and active in management domain」「Vlans in spanning tree forwarding state and not pruned」の3行が並ぶ。一番下の行に対象VLANが入っていなければ、そのVLANはトランク上で実際にはフォワーディングされていない。Allowed列だけ見て安心するとハマるので注意。
add忘れで既存VLANを上書きする事故
Trunkで明示的に switchport trunk allowed vlan を設定するとき、最大の落とし穴は「addを付け忘れて上書きする」こと。これ、教科書では1行さらっと書いてあるだけだけど、現場の事故率はぶっちゃけかなり高い。
! 既存設定(VLAN 10,20,30が許可されている状態) SW-A(config)# interface gigabitEthernet 0/1 SW-A(config-if)# switchport trunk encapsulation dot1q SW-A(config-if)# switchport mode trunk SW-A(config-if)# switchport trunk allowed vlan 10,20,30 ! あとから VLAN 40 を追加するつもりで... SW-A(config-if)# switchport trunk allowed vlan 40 ! ↑ これで allowed vlan は「40だけ」に上書きされる
switchport trunk allowed vlan 40 と打つと、既存のVLAN 10,20,30が消えて「40のみ許可」に変わる。本番環境でこれをやると、関係ない他のVLANまで一気に通信不能になる大事故になる。VLANを追加するときは必ず add を付けること。
! VLAN 40 を追加(既存に追加) SW-A(config-if)# switchport trunk allowed vlan add 40 ! VLAN 30 を削除 SW-A(config-if)# switchport trunk allowed vlan remove 30 ! 全VLAN許可に戻す(all指定) SW-A(config-if)# switchport trunk allowed vlan all ! 確認 SW-A# show interfaces gigabitEthernet 0/1 trunk Port Mode Encapsulation Status Native vlan Gi0/1 on 802.1q trunking 1 Port Vlans allowed on trunk Gi0/1 10,20,40 Port Vlans allowed and active in management domain Gi0/1 10,20,40 Port Vlans in spanning tree forwarding state and not pruned Gi0/1 10,20,40
ちなみに show interfaces trunk の最終行(in spanning tree forwarding state…)に対象VLANが出ていなければ、STPかVTPプルーニング、もしくはVLAN自体がshutdown状態になっていることもある。Cisco公式の 802.1Qトランク設定ガイド でも、Allowed VLANsとActiveの差は明確に区別されている。
CDP警告が出ているのに気づかないパターン
802.1Qトランクには「Native VLAN」という概念がある。タグを付けずに送信されるVLANのことで、デフォルトではVLAN 1。両端でNative VLANが一致していないと、Native扱いVLANのフレームだけが消える。しかも厄介なのは、エラーログには出るけどリンクは Up し続ける点。
図1: 障害発生率と気づきにくさの比較
75%
55%
35%
※ 自分が過去5年で対応した約120件のTrunk障害における体感比率
SW-A# show interfaces gigabitEthernet 0/1 trunk Port Mode Encapsulation Status Native vlan Gi0/1 on 802.1q trunking 1 <- 片側 ! 対向側 SW-B# show interfaces gigabitEthernet 0/1 trunk Port Mode Encapsulation Status Native vlan Gi0/1 on 802.1q trunking 99 <- 不一致 ! ログにも警告が出る *Apr 26 02:14:33: %CDP-4-NATIVE_VLAN_MISMATCH: Native VLAN mismatch discovered on GigabitEthernet0/1 (1), with SW-B GigabitEthernet0/1 (99).
! 両端のスイッチで同じNative VLANを設定 SW-A(config)# interface gigabitEthernet 0/1 SW-A(config-if)# switchport trunk native vlan 99 SW-B(config)# interface gigabitEthernet 0/1 SW-B(config-if)# switchport trunk native vlan 99 ! セキュリティ的にはNative VLAN専用のVLANを切り、未使用にするのが推奨 ! 例:VLAN 999 をNative専用、どのアクセスポートにも割り当てない
Native VLANをデフォルトの1のまま放置すると、VLANホッピング攻撃のリスクが残る。本番環境では未使用のVLAN(例:999)をNative専用にして、アクセスポートには絶対に割り当てない運用が定石。あと、switchport trunk native vlan tag でNativeフレームにもタグを付ける運用もアリ。
switchport mode dynamic auto の罠
CiscoスイッチはデフォルトでDTP(Dynamic Trunking Protocol)が有効になっている。両端ともdynamic autoだと、誰もtrunkを宣言しないので結果として両側Accessになる。これがけっこう厄介で、片側だけ switchport mode trunk を打って満足していると、対向がdynamic auto のままでAccess動作している、という悲劇が起きる。
| SW-A側 | SW-B側 | 結果 |
|---|---|---|
| trunk | trunk | Trunk |
| trunk | dynamic desirable | Trunk |
| trunk | dynamic auto | Trunk |
| dynamic auto | dynamic auto | Access(両端) |
| access | trunk | 不一致(通信不安定) |
SW-A# show interfaces gigabitEthernet 0/1 switchport Name: Gi0/1 Switchport: Enabled Administrative Mode: dynamic auto <- 設定値(意図) Operational Mode: static access <- 実際の動作(Accessになってる!) Administrative Trunking Encapsulation: negotiate Operational Trunking Encapsulation: native Negotiation of Trunking: On Access Mode VLAN: 1 (default) Trunking Native Mode VLAN: 1 (default)
「Administrative Mode」と「Operational Mode」がズレているのが見えるはず。設定では trunk のつもりが、実際は access として動いている、というやつ。これに気づかず数時間ハマる人をこれまで何人も見てきた(自分も含む)。
両端 dynamic auto のまま放置するのは絶対NG。本番Trunkは必ず switchport mode trunk で固定し、さらに switchport nonegotiate でDTPフレーム自体を止めるのがベストプラクティス。これでDTP由来のVLANホッピング攻撃も防げる。
VLAN 20だけ通らない状態を再現→修正の手順
手元のCatalyst 2960(IOS 15.2(7)E)2台と、各VLANに繋いだPCで、実際に「allowed vlanからVLAN 20を抜く→疎通NG→addで戻す→疎通OK」を確認した。再現手順を載せておく。
SW-A(config)# interface gigabitEthernet 0/1 SW-A(config-if)# switchport trunk allowed vlan 10,30 SW-A(config-if)# end ! PC-A2 (VLAN 20, 192.168.20.10) から PC-B2 (192.168.20.20) にping PC-A2> ping 192.168.20.20 Request timeout for icmp_seq 0 Request timeout for icmp_seq 1 Request timeout for icmp_seq 2 ^C
SW-A# show interfaces gigabitEthernet 0/1 trunk Port Vlans allowed on trunk Gi0/1 10,30 <- VLAN 20 が無い! Port Vlans in spanning tree forwarding state and not pruned Gi0/1 10,30 <- ここにも無い、確定
SW-A(config)# interface gigabitEthernet 0/1 SW-A(config-if)# switchport trunk allowed vlan add 20 SW-A(config-if)# end SW-A# show interfaces gigabitEthernet 0/1 trunk Port Vlans allowed on trunk Gi0/1 10,20,30 <- 戻った PC-A2> ping 192.168.20.20 64 bytes from 192.168.20.20: icmp_seq=0 ttl=64 time=0.421 ms 64 bytes from 192.168.20.20: icmp_seq=1 ttl=64 time=0.398 ms
この一連の流れ、慣れれば3分かからない。逆に言うと、最初の show interfaces trunk で「Vlans in spanning tree forwarding state and not pruned」を確認する癖さえ付ければ、半分以上のTrunk障害は瞬殺できる。
この5本だけ覚えておけば足りる
| コマンド | 用途 | 見るポイント |
|---|---|---|
| show interfaces trunk | Trunk全体の状態確認 | Allowed/Active/Pruned行 |
| show interfaces switchport | Admin/Operationalの差確認 | Operational Mode行 |
| show vlan brief | VLAN存在・状態確認 | Status列がactive |
| show cdp neighbors detail | 対向Native VLAN確認 | Native VLAN行 |
| show mac address-table interface | 学習しているVLAN/MAC確認 | VLAN列 |
余談だけど、show interfaces trunk はvty経由でログ取得しておくと、後から「いつallowed vlanが変わったか」の追跡に使える。自分は障害対応の最初に必ず両端のスナップショットを取る癖をつけている。後で「設定変えてないですよね?」みたいな話になったときの保険。
Trunk障害は「3パターン+5コマンド」で片付く
Trunkポートで特定VLANだけ通信できない原因は、ほぼ ①allowed vlanの設定漏れ ②Native VLAN不一致 ③DTPでaccess化、の3つに集約される。最初に show interfaces trunk で「Vlans in spanning tree forwarding state」行を確認し、次に show interfaces switchport でAdministrative/Operational Modeの差を見る。この2本でほぼ原因が見える。allowed vlan追加時は必ず add を付けること、本番Trunkは nonegotiate で固定することを習慣にすれば、同じ事故はもう起きない。
よくある質問(FAQ)
Q. switchport trunk allowed vlan を打ったら他のVLANが消えました。戻せますか?
戻せる。switchport trunk allowed vlan all で全VLAN許可に戻せるし、必要なVLANだけ switchport trunk allowed vlan 10,20,30,40 のようにカンマ区切りで明示的に並べ直せばOK。ただし本番中なら、まずは all で広めに開けて疎通復旧→落ち着いてから絞る、の順がおすすめ。
Q. Native VLANが不一致でもリンクUpしているのは何故ですか?
Native VLAN不一致はL2の設定エラーであって、物理層・データリンク層のリンク確立には影響しないから。CDPがログで警告を出すだけで、Trunk自体は動作し続ける。タグ無しフレームの扱いだけがズレるので、Native扱いVLANのフレームが対向の別VLANにマッピングされる、という現象になる。これがVLANホッピング攻撃の温床になるので、運用上は必ず両端を揃える。
Q. switchport mode trunk と switchport mode dynamic desirable はどう違うんですか?
trunk は無条件にTrunk動作を強制するモード。dynamic desirable はDTPで対向と交渉して、対向がtrunk/desirable/autoのいずれかならTrunkになるモード。本番ではDTPの不確実性を避けるため、switchport mode trunk + switchport nonegotiate の組み合わせで明示的に固定するのが定石。dynamic系は実験用と割り切ってOK。
Q. show interfaces trunk に「Vlans allowed on trunk」が10-4094と出ています。普通ですか?
普通。switchport trunk allowed vlan all またはallowed vlanを明示設定していない場合のデフォルト動作で、Catalystでは1-4094全てが許可される(Cisco IOSバージョンや機種によっては表示が10-4094のように一部範囲で出ることもある)。セキュリティ的には必要なVLANだけに絞る方が望ましいけど、検証環境ならそのままでも問題なし。


