MTU設定ミスでTCP再送多発『トランスポート層の話⑧』
「小さいデータは通るのに、ファイル転送やAPIでやたら遅い/途中で固まる」——こういう時はMTU(最大転送単位)の不一致を疑います。経路のどこかで実際に通せるサイズより大きいフレームを投げると、分断(Fragment)やPMTUDブラックホールが起き、TCPは再送を連発。スループットが一気に崩れます。
症状の出方
Wiresharkやtcpdumpで**[TCP Retransmission]**が多発、RTOが伸びる
小さいパケットはOK、大きい応答だけタイムアウト
VPN/PPPoE/トンネル(MTUが小さい)経由の通信だけ遅い(直結は速い)
クラウド境界やFWを跨ぐと遅い/場所により再現
典型要因
トンネルやタグのオーバーヘッド(IPsec/GRE/VXLAN/QinQ/PPPoE)でヘッダーが大きい分、実効MTUが縮む
ICMP “Fragmentation Needed” をFWが遮断 → PMTUDが働かずブラックホール
片側IFだけMTU固定設定、対向はデフォルト(1500)のまま
MSS調整(TCPオプション)なしでWAN越え
図:PMTUDブラックホールの典型
Client (MTU1500) ---- [FW] ---- (IPsecトンネル MTU=1420) ---- Server
1500B送出 → 途中で分断必要
└─ ICMP "Frag Needed" をFWがブロック
→ クライアントはサイズを下げられず、再送→再送→タイムアウト
最短の切り分け手順
事実を取る(パケット)
tcpdump -ni <if> 'tcp and (host <相手>)':Retransmission/Out-of-orderが増えていないか
可能ならICMP Type3 Code4(Frag Needed)の有無も併せて見る
DF付きpingで“通る最大”を測る
Linux: ping -M do -s 1472 <相手>(1472+IP/ICMP=1500想定、成功するまで-sを下げる)
Windows: ping -f -l 1472 <相手>
Cisco: ping <相手> size 1472 df-bit
IFとトンネルのMTUを確認
ルータ/スイッチ:show interface | include MTU / show ip interface
OS: ip link / netsh interface ipv4 show subinterfaces
経路中のFW/LBでICMPが落ちていないか
FWログ/ポリシー:ICMP Type3 Code4 をallow(または関連通信として許可)
具体的な対処
MSSクランプ(推奨)
経路の最小MTUに合わせてTCP MSSを小さく広告し、アプリの送出サイズを抑える。Cisco(WAN側IFのin/outどちらか、片側で十分なことが多い)
interface GigabitEthernet0/0 ip tcp adjust-mss 1360
Linux(iptables/nftables 等で --set-mss)
目安:IPsecやPPPoEなら1360〜1410あたりから開始し、実測で詰める。
トンネル/IFのMTUを正しく設定
PPPoEなら物理1500でも実効1492、IPsec/GREなら更に小さく。
mtu 1400(例)など経路最小に整合させる。
ICMP “Frag Needed” を通す
ステートフルFWなら関連ICMPをpermit。ステートレスACLではType3 Code4を明示許可。
経路設計の見直し
2重トンネルやQinQ+VXLANなど多層カプセル化の同居を避ける/区切る。
どうしても多層なら、最外周で適正なMSSクランプを徹底。
変更後の確認
tracepath <相手>(Linux)でpmtuが期待値になっているか
DF付きpingの通過サイズが改善したか
実アプリで再送数/RTTが下がり、スループットが回復したか(iperf3 -M <MSS>も有効)
再発防止チェックリスト
ルータ/トンネル/PPPoEでMTU表を管理(物理/論理/実効の3列)
変更手順にDF付きpingとtracepathを組込み
FW標準ポリシーでICMP Type3 Code4を許可
WAN越えはMSSクランプ標準化(初期値と根拠を明記)
まとめ
MTUの食い違いは、表面上は「遅い」「途切れる」ですが、実体はPMTUD不全+TCP再送祭り。
DF付きping→IF/トンネルMTU→ICMP許可→MSSクランプの順で詰めると、数分で原因点に到達できます。
