ネットワークの「見えない断崖」:MTU不一致が引き起こすパケットの悲劇
ネットワークエンジニアとして現場を渡り歩いていると、幾度となく「なぜか特定の通信だけが異常に遅い」「大きなファイルを転送すると決まって固まる」という怪奇現象に遭遇します。アプリ開発者がどれほどコードを最適化しても、DB管理者がクエリをチューニングしても解決しない。その原因の多くは、下位レイヤー、具体的にはMTU(Maximum Transmission Unit)の不一致という「見えない断崖」にあります。
今日は、ジャンボフレームを導入する際、あるいはクラウド環境へ移行する際に多くのエンジニアが陥る「MTU不一致によるパケット断片化」の深淵を覗いていきましょう。
—
1. なぜ「1500」という数字が呪縛となるのか
イーサネットの標準的なMTUは1500バイトです。これは歴史的な経緯やコスト、技術的な制約が積み重なった結果ですが、現代のデータセンターや高速ネットワークでは、オーバーヘッドを減らしてスループットを稼ぐために「ジャンボフレーム(9000バイト等)」を有効にすることがあります。
ここで問題になるのは、エンドツーエンドの「経路のどこか一箇所でもMTUが小さいと、その先の機器がパケットを処理しきれない」という単純かつ残酷な事実です。
経路上の断片化(Fragmentation)の結末
送信側が9000バイトのパケットを送り出した際、経路上のルーターが「おっと、次のリンクはMTUが1500しかないぞ」と判断すると、ルーターはパケットを分割(フラグメンテーション)せざるを得ません。
- ルーターの負荷増大: 全てのパケットをCPUで分解・再構築するのは、ルーターにとって重い処理です。
- ドロップの誘発: もしパケットに
DF(Don’t Fragment)ビットが立っていれば、ルーターはそのパケットを即座に破棄し、送信側にICMP Type 3 Code 4(Destination Unreachable / Fragmentation Needed)を返します。 - 「パスMTUブラックホール」の発生: セキュリティポリシーでICMPを全遮断しているネットワークでは、このエラー通知が届かず、通信が永遠にタイムアウトし続ける「ブラックホール」状態に陥ります。
—
2. 現場で使えるデバッグの極意:pingによるMTU調査
トラブルシューティングの第一歩は、どのサイズまで通信が通るかを物理的に確認することです。pingコマンドのオプションを使い、ペイロードサイズを指定してパケットを送り込みましょう。
# macOS/Linuxの場合:-DはDFビットの設定、-sはペイロードサイズ
# 1472(ペイロード) + 20(IPヘッダー) + 8(ICMPヘッダー) = 1500バイト
ping -D -s 1472 192.168.1.1
# もしジャンボフレーム(9000)をテストするなら
# 8972 + 20 + 8 = 9000バイト
ping -D -s 8972 192.168.1.1
もしpingが通らない場合、その経路のどこかにMTUのボトルネックが存在します。
—
3. 実装レベルでの確認:curlとTCP MSS
Web APIを開発していると、curlを使ってレスポンスを確認することが多いはずです。ここで、「ヘッダーは取れるのにボディが受信できない」という現象はMTU問題の典型です。
# -v オプションで通信の詳細を表示
# 途中で止まる場合は、MTUの不一致を疑う
curl -v https://api.example.com/large-data
また、TCP通信にはMSS(Maximum Segment Size)という概念があります。これはMTUからIPヘッダーとTCPヘッダーの分を引いた値です(通常1460バイト)。通信開始時の3ウェイ・ハンドシェイクで、双方のNICがこのMSSをネゴシエーションしますが、途中のルーターが勝手にパケットを弄ると、この整合性が崩れます。
PythonによるMTU確認(Scapyを用いたパケット解析)
より高度な調査が必要な場合、Scapyを使ってパケットのフラグを直接確認することもあります。
from scapy.all import IP, ICMP, sr1
# DFビット(flags=2)を立てて、特定のサイズのパケットを送る
pkt = IP(dst="192.168.1.1", flags=2)/ICMP()/"X"*1472
reply = sr1(pkt, timeout=2)
if reply:
print("通信成功: MTUは1500以上です")
else:
print("通信失敗: パスMTUが小さいか、ICMPが遮断されています")
—
4. インフラエンジニアへの処方箋:設定上の注意点
もしあなたがクラウドのVPCやオンプレミスのスイッチを設定しているのであれば、以下の「鉄則」を守ってください。
1. 一貫性の保持: 全経路(ホストNIC、物理スイッチ、ルーター、VPNトンネル)のMTUを必ず合わせる。
2. クラウド環境の特殊性: AWSやGCPなどのクラウド環境では、インスタンスのMTUが9001バイト(ジャンボフレーム対応)であっても、通信先のロードバランサーや外部ネットワークが1500バイト固定であることが多々あります。
3. MSSクランプの設定: どうしてもMTUを統一できない場合、ルーター側でTCP MSS Clampingを有効にしてください。これは、TCPのSYNパケットを監視し、MSS値を強制的に書き換えることで、フラグメンテーションを防ぐ救済措置です。
Cisco系機器でのMSSクランプ例:
interface GigabitEthernet0/1
ip tcp adjust-mss 1460 # TCP通信に対してMSSを1460に制限
—
最後に:ネットワークは「正直」である
MTU問題は、ネットワークが非常に正直であることを教えてくれます。設定の不整合は、たとえわずかな差であっても、必ずパケットの破棄やレイテンシの増大として現れます。
「なぜか遅い」という直感を感じたら、まずはMTUを疑ってください。コマンド一つ、設定一行の修正で、今まで悩んでいたパフォーマンスの問題が霧のように消え去る瞬間こそ、この仕事の醍醐味です。
皆さんのインフラが、今日も高いスループットを維持し、パケットロスなく駆け巡ることを願っています。それでは、また現場でお会いしましょう。
コメント