【実務・中級編】 MTUミスマッチに起因するフラグメンテーションとDFビットの問題 – インフラ・物理&L2/L3ネットワーク基礎実践ガイド

ネットワークの「静かなる殺人者」:MTUミスマッチとPMTUDの深淵を解き明かす

ネットワークエンジニアとして現場に長く立っていると、奇妙な現象に遭遇することがあります。「小さなテキストは飛ぶのに、大きなJSONや画像を投げるとタイムアウトする」「なぜか特定のAPIだけが死ぬ」といった類のアレです。

Wiresharkを開き、パケットの海を泳いでみると、そこには決まって犯人がいます。そう、MTU(Maximum Transmission Unit)ミスマッチです。

今日は、パケットが経路上で無残にも破棄され、通信がブラックホールに吸い込まれていくメカニズムと、その解決策である PMTUD(Path MTU Discovery)の深淵について、現場の視点から紐解いていきましょう。

—

1. なぜ「パケット破棄」は起きるのか?

イーサネットの標準的なMTUは 1500 bytes です。しかし、VPNトンネル(IPsecやGRE)、VXLAN、あるいはクラウド環境の仮想ネットワークを経由すると、カプセル化オーバーヘッドが発生し、実効MTUは 1500 を下回ります。

もし、送信元が 1500 bytes のパケットを送り出し、経路上のどこかのルーターが 1400 bytes しか扱えないインターフェースを持っていたらどうなるか。ここで登場するのが DF(Don’t Fragment)ビットです。

DFビットとICMP Type 3 Code 4のダンス

DF=1 がセットされたパケットがMTU制限を超えるルーターに到達すると、ルーターは律儀にパケットを破棄します。そして送信元に対して、「ICMP Destination Unreachable (Fragmentation Needed and DF set)」という怒りのメッセージを返送します。

これがネットワークにおけるPMTUDのスタート地点です。送信元はこのメッセージを受け取り、「ああ、この経路はこれ以上大きいパケットを送っちゃいけないんだな」と学習し、MSS(Maximum Segment Size)を調整して再送を試みます。

—

2. 現場を悩ませる「ブラックホールルーター」

しかし、現実はそう甘くありません。セキュリティポリシーや過剰なACL設定により、この「ICMPメッセージ」が経路上のどこかで捨てられてしまうことがあります。

これが「PMTUDブラックホール問題」です。送信元はパケットを送ったまま返事も来ず、パケット破棄の通知も届かない。結果、TCPのハンドシェイクは成功するのに、データ転送フェーズで永久に固まるという、極めてデバッグ難易度の高い状況が完成します。

—

3. 実践:トラブルシューティングとデバッグ

では、目の前の通信がMTU問題で詰まっているかをどう見極めるか。まずは ping のサイズ指定で物理的な限界を探るのが定石です。

Linuxでの確認コマンド例

以下のコマンドで、フラグメント不可(DFビットあり)を指定しつつ、サイズを徐々に大きくして送り出します。

# 1472 bytes + IPヘッダー(20) + ICMPヘッダー(8) = 1500 bytes
# -M do は DFビットをセットするオプション
ping -M do -s 1472 <ターゲットIP>

もし 1472 で通り、1473 で Frag needed が返ってくるなら、その経路のMTUは 1500 です。これが返ってこずにタイムアウトする場合、ICMPが遮断されています。

—

4. Web API開発者が知るべき「MSSクランプ」

開発者として、「APIが繋がらない」と報告を受けた際、サーバー側で最も即効性のある対策は MSS Clamping です。これはTCPのハンドシェイク中に、双方の MSS を強引に書き換えて、大きなパケットが生成されないようにする手法です。

もしあなたがLinuxサーバーの管理者であれば、iptables で以下のように設定できます。

# TCP SYNパケットのMSSを1360に強制書き換えする(カプセル化のオーバーヘッドを考慮)
iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1360

Pythonでパケットサイズを意識した通信をする

Pythonで requests を使う場合、デフォルトではOSの挙動に依存しますが、巨大なデータを扱う際はバッファサイズやチャンク処理を意識することが重要です。

import requests

# 巨大なJSONをPOSTする際は、ストリーム配信を検討する
with open('large_payload.json', 'rb') as f:
    response = requests.post(
        'https://api.example.com/data',
        data=f,
        headers={'Content-Type': 'application/json'}
    )
# ストリーム処理を行えば、メモリ効率だけでなく、
# パケットのフラグメンテーションに対しても堅牢な設計が可能になる

—

5. スペシャリストからの提言

MTU問題は、インフラのレイヤーが複雑化する現代において、避けては通れない壁です。

1. Path MTU Discoveryを信じすぎない: ICMPを無効化するファイアウォールは依然として多い。
2. MSS Clampingを武器にする: インフラの出口で適切にMSSを制限することは、恥ではありません。むしろ「安定した通信」を保証する高度なエンジニアリングです。
3. パケットキャプチャを恐れない: tcpdump -i eth0 'tcp[tcpflags] & (tcp-syn|tcp-ack) != 0' のようなフィルタを使い、ハンドシェイク時の MSS 値を読み解けるようになれば、あなたはもうネットワークスペシャリストの領域にいます。

ネットワークのトラブルは、多くの場合「目に見えない場所」で起きています。だからこそ、プロトコルの挙動を正しく理解し、パケットの断末魔(ICMP)を聞き逃さない姿勢が、あなたのサービスを救う唯一の鍵になるのです。

さあ、今日もプロトコルの深淵を楽しみましょう。なにか疑問があれば、いつでもWiresharkを片手に聞きに来てください。

コメント

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