VPNが「MTUのせいでパケットを失っている」と言われ、トンネルを1400に設定したら転送が再び動いた。その結果は診断のように感じられる。たいていは算数の偶然だ——特定したことのない上限の下に収まるだけの小さな数を選んだだけで、次のネットワークでは別の予算で同じ上限にまた出会う。

これをほとんど引き起こしているのは二つの神話だ。一つ目は、トンネルインターフェースのMTUが経路のMTUだというもの。二つ目は、カプセル化のコストは「ヘッダー一つ」で、PPPoEは数える価値もないというもの。どちらも、選んだ数値が恣意的に見えるのに実際には決まっている、という形で間違っている。

神話その一:トンネルのMTUは経路のMTUである

トンネルインターフェースに設定する値は、実装が下位に渡す最大の内側パケットについてのローカルな約束だ。経路の実際の容量は、あなたと遠端の間のすべてのリンクの性質であり、ルートが変わるとき、モバイル接続がハンドオーバーするとき、トラフィックが別のピアリングを通るときに変わりうる。設定した1500は自分のホストが何を組み立てるかを示すだけで、ネットワークが何を運ぶかではない。

経路MTU探索はその二つを調和させるために存在し、フィードバックに依存する。IPv4では、フルサイズのパケットを転送できないルーターがICMPの「fragmentation needed」を送るべきで、送信側は推定値を下げる。IPv6では相当するのはPacket Too Bigメッセージで、ルーターは中継で一切フラグメントしない。そのフィードバックがフィルタされると、送信側は経路が運べないパケットを作り続け、理由を誰も教えてくれない。

神話その二:カプセル化のコストはヘッダー一つ

外側の層を正直に数えよう。外側のIPヘッダーはIPv4で20バイト、IPv6で40バイト。NAT越えのUDPカプセル化が8を足す。トンネルプロトコルは独自のヘッダー、初期化ベクトルまたはnonce、暗号のブロック境界や整列境界までのパディング、トレーラー、整合性チェック値を足す。プロトコルと暗号によって、内側のパケットが始まる前に合計は余裕で数十バイトに達する。

さらに内側のパケット自身のヘッダーを引く。トンネル内のTCPセグメントは自分の20バイトのIPヘッダーと20バイトのTCPヘッダーを運び、TCPのMSSはトンネルの公称ペイロードではなくMTUから導かれる。だからpingは小さいペイロードなら成功するのにファイル転送が止まる——道具が試しているものが違い、フルサイズのTCPセグメントを実際に使うのは一つだけだからだ。

ip link show tun0
ping -M do -s 1472 192.0.2.10
ping -M do -s 1400 192.0.2.10

最初のコマンドは設定されたトンネルMTUを報告する。二つのプローブは1472バイトのペイロードを送り、これはIPv4とICMPのヘッダー28バイトを加えて1500バイトのパケットになり、次に小さいものを送る。大きいプローブが完全に失敗し小さい方が成功すれば、経路全体の問題ではなくサイズ依存の障害だ。

神話その三:PPPoEは今でもきれいな1500をくれる

従来のPPPoEアクセス回線は1500バイトのIPパケットを運ばない。PPPoEヘッダーとPPPプロトコルフィールドがEthernetフレーム内で8バイトを占め、IPパケットには1492が残る。これがRFC 2516に書かれた従来の上限だ。そのような回線でVPNを動かすと、トンネルのオーバーヘッドは1500からではなく、その1492から出てくる。

RFC 4638は、アクセスコンセントレーターと顧客側装置の両方が対応している場合に、より大きなPPPペイロードを交渉する方法を定めているので、「この接続はPPPoEを使っている」だけでは特定の数値を証明しない。ローカルの設定は、一度も設定されたことのないパケットを中間装置に受け入れさせることはできないので、有用な問いは、ラベルが何と言うかではなく、回線が実際に何を交渉したかだ。

障害が選択的に見える理由

小さなリクエストが成功し大きな転送が止まるのは、経路MTUのブラックホールの典型的な兆候だ。ハンドシェイク、DNSクエリ、API呼び出しはすべて収まるが、一括転送はフルサイズのセグメントを生み、それが一つのリンクで死に、問題を知らせるはずのICMPメッセージは決して届かない。接続は正常に見え、ダウンロードが固まるので、人は経路ではなくサーバーを見に行く。

二つ目の関連する誤りは、三つの数値を混同することだ——インターフェースMTU、TCPのMSS、そしてプロトコル自身のフラグメント化やパディングの設定。ルーターでのMSSクランプは告知するMSSを書き換えて送信側に小さなセグメントを作らせるが、トンネルMTUを変えるわけでもUDPトラフィックを助けるわけでもない。関連して見えるからと三つに同じ数値を与えるのが、善意の変更が動いている設定を壊す道だ。

何を、どの順で変えるか

証拠から始めよう。上のプローブで障害がサイズ依存だと確認し、通る最小のサイズと失敗する最大のサイズを見つける。トンネルを疑う前にアクセス回線の実際のMTUを確認する(PPPoE回線はVPNが触れる前に予算を制限している)。変更を戻せるよう元の値を記録しておく。

次にクライアントが文書化している最小の調整を適用する。多くのクライアントはトンネルMTUとMSS修正オプションを提供し、MSSオプションはすべてのパケットを小さくせずに送信側へ届くので、TCPにはしばしばより良いてこになる。同じ宛先と同じ転送を再試験し、落ち着いた数値を記録する。一つのアクセス網で動くトンネル値は普遍定数ではなく、次の現場には独自の予算がある。

関連記事