認証の「門番」を解剖する:EAPOLフレームの深淵と実務的トラブルシューティング
ネットワークエンジニアとして現場に立っていると、上位レイヤーのHTTP/3やgRPCの話に花が咲く一方で、足元のL2レイヤーで起きている「沈黙」に頭を抱えることがよくあります。特にIEEE 802.1X認証が絡む環境では、認証が通らないという事象に対し、ただ「設定ミスでしょう」と決めつけるのは禁物です。
今日は、スイッチのポートにLANケーブルを差し込んだ瞬間に繰り広げられる、認証の「握手」――EAPOL(Extensible Authentication Protocol over LAN)の正体を徹底的に解剖します。
—
1. EAPOLとは何か:イーサネットを「認証のトンネル」に変える魔法
EAPOLは、IEEE 802.1Xの核心です。通常、EAPはPPP(Point-to-Point Protocol)上で動作するように設計されていましたが、これをイーサネット環境で無理なく動かすために生まれたのがEAPOLです。
物理層でのリンクアップ直後、サプリカント(PC等の端末)は、オーセンティケータ(スイッチ)に対してEAPOLパケットを投げ込みます。この時、IPアドレスすら割り当てられていない「無防備な状態」で通信を行うため、通常のIPヘッダーではなく、イーサネットフレームの直上にEAPOLを載せるという荒技を使います。
EAPOLフレームの構造
EAPOLは、イーサネットフレームの「タイプフィールド」に 0x888E を指定することで、スイッチ側のプロトコルスタックが「これは認証用パケットだ」と即座に判断できるように設計されています。
- Destination MAC:
01:80:C2:00:00:03(IEEE 802.1X ポートアクセスエンティティのマルチキャストアドレス) - EtherType:
0x888E - EAPOL Header: バージョン、タイプ、データ長
- EAP Packet: 実際の認証データ(ID要求やレスポンスなど)
この 01:80:C2:00:00:03 というマルチキャストアドレスが重要です。多くのスイッチでは、このフレームをCPUにダイレクトに引き渡すため、トポロジ内の途中にこのアドレスをフィルタリングしてしまうL2スイッチやハブがあると、認証は一瞬で詰みます。
—
2. パケットタイプが語る「交渉」のシーケンス
現場でWiresharkを叩いたとき、まず注目すべきは EAPOL Type です。主なものは以下の4つです。
| Type | 名称 | 役割 |
| :— | :— | :— |
| 0x00 | EAP-Packet | 本丸。EAPメッセージの搬送用。 |
| 0x01 | EAPOL-Start | サプリカントからの「認証させてくれ!」という合図。 |
| 0x02 | EAPOL-Logoff | 通信終了。ポートを未認証状態に戻す。 |
| 0x03 | EAPOL-Key | EAPOL-Key。WPA/WPA2/WPA3等の暗号化鍵の配布に使用。 |
認証フローの典型はこうです。
1. サプリカント: EAPOL-Start を送信。
2. スイッチ: EAP-Request/Identity を送信。
3. サプリカント: EAP-Response/Identity(IDを回答)を送信。
4. スイッチ: Radiusサーバーと連携し、検証開始。
トラブルシューティングの際、EAPOL-Start は飛んでいるのに EAP-Request が返ってこない場合、スイッチ側の設定(dot1x system-auth-control 等)が漏れているか、ポートが「強制認証(force-authorized)」モードになっていないかを真っ先に疑います。
—
3. 実務でのデバッグ:Pythonで「認証の影」を追う
実務では、生のパケットをキャプチャするだけでなく、認証プロセスのシミュレーションが必要な場面もあります。scapy を使えば、EAPOLパケットを構築してスイッチの挙動をテスト可能です。
from scapy.all import *
# ターゲットスイッチの認証用マルチキャストアドレス
EAPOL_DST = "01:80:c2:00:00:03"
# EAPOL Startパケットの構築
# Ethernetヘッダー + EAPOLヘッダー(Type 1: Start)
pkt = Ether(dst=EAPOL_DST, src=get_if_hwaddr("eth0"), type=0x888E) / \
EAPOL(version=2, type=1) # type 1 = EAPOL-Start
# 送信してスイッチの反応を待機
sendp(pkt, iface="eth0")
print("EAPOL-Startを送信しました。認証パケットの到着を待ちます...")
# スイッチからのRequest/Identityをキャプチャする準備
sniff(filter="ether proto 0x888e", count=1, timeout=5)
このコードを実行し、スイッチが即座に EAP-Request/Identity を返してくるかを確認してください。もし返ってこなければ、L2レベルでの疎通遮断、またはスイッチの認証ポートが「シャットダウン状態」あるいは「未設定」である可能性が高いです。
—
4. 現場の教訓:設定の罠とTips
最後に、運用現場でよく踏む地雷を共有します。
- ポートFast設定の罠: Ciscoスイッチなどで
spanning-tree portfastを入れていない場合、リンクアップ直後のスパニングツリーのリスニング/ラーニング期間が原因で、端末が投げるEAPOL-Startがスイッチに届かず、タイムアウトします。 - VLAN変更のタイミング: 認証成功後に
Voice VLANやDynamic VLANを割り当てる際、スイッチ側でVLANが未作成だとポートがエラーになります。show vlan briefを常に正としてください。 - MTU問題: EAPOLは小さいパケットですが、RADIUSサーバーとのやり取りで証明書(EAP-TLS)が巨大化すると、MTU値の調整が必要になることがあります。
最後に
EAPOLは、目に見えない「信頼」をコード化する儀式です。パケットをキャプチャし、その中身を覗き込むことで、ネットワークは単なる「箱」から「対話相手」へと変わります。もし現場で認証が通らず途方に暮れたら、まずは 0x888E が正しく流れているか、そこから全てを紐解いてみてください。
プロトコルの深淵を覗くことは、インフラエンジニアにとって最高の知的なエンターテインメントです。それでは、良きパケットライフを。
コメント