固定の1,500バイト内部パケットをVPN越しに通す
固定の1,500バイト内部パケットは1,500バイトの外部経路には収まらない。オーバーヘッドを測定し、より大きなアンダーレイMTUか対応済みのフラグメンテーションを選ぶ。
譲れない要件がある。送信側が出力するのと同じ1,500バイトのIPパケットを、ヘッダーも含めて対向側が受け取らなければならない。トンネルは、そのパケットに自身のフレーミングを加えたものを二つ目の1,500バイトIPパケットの中に包み込むことはできない。つまり設計のどこかが譲らなければならない。以下の順序は、私が変更ウィンドウで使っているものである。バイト予算を書き、アンダーレイが実際に運べるものを証明し、搬送機構をちょうど一つ選び、対向側で内部パケットを確認する。
プロファイルを編集する前にバイト予算を書く
カプセル化は複数の層でバイトを追加し、その合計は調べて引ける定数ではなく、あなたのプロファイルの性質である。アドレスファミリー、暗号の選択、トランスポートプロトコル、圧縮やフレーミングの各オプションがすべて数値を動かす。だから他の配備からコピーした引き算は予算として役に立たない。内部要件から始め、自分の設定の実測済みパケットごとのオーバーヘッドを加え、その結果の外側サイズを、誰かがファイルを編集する前に変更チケットに書く。
二つの数値が設計を決める。経路がフラグメンテーションなしで運ぶ最大の外部パケットと、カプセル化が必要とする追加バイトである。前者が後者に1,500を足した値より小さいとき、どちらかを変えなければならない。そのとき選択肢は創造的ではなく狭くなる。だから私は選択肢を論じる前に両方の数値を書き留める。トンネル層でそれらのバイトを圧縮して消すものはなく、単一のMTU整数であなたに与えられた要件が消えることもない。
do-not-fragment ping でアンダーレイを探る
インターフェースMTUを信じずに経路を測定する。外部経路で最小のリンクが効くからである。Linux では, -M do が do-not-fragment ビットを立て, -s が ICMP ペイロードを指定するので、20バイトの IP ヘッダーと8バイトの ICMP ヘッダーを引くと、1,500バイトのフレームは1,472バイトのペイロードで応答する。プローブが失敗するまでペイロードを上げ、次にジャンボサイズへ飛んで経路がそもそも運ぶかを確かめる。
ping -M do -s 1472 -c 2 198.51.100.10 ping -M do -s 8972 -c 2 198.51.100.10 tracepath -n 198.51.100.10
1,472は通り8,972は通らない経路は、1,500バイトの内部パケットとオーバーヘッドを単一の外部パケットで運べない。これが VPN 設定を開く前に必要だった答えである。さらに、次の二つの節のどちらが当てはまるかも決まるので、二つのプローブ結果をチケットの隣に置いておく。ここでの推測は保守ウィンドウを一つ失う。自分を up と報告するトンネルは、経路が受け入れる最大パケットについて何も教えてくれないからである。
経路MTUを上げるのは全ホップが同意する場合だけ
ジャンボフレームはエンドツーエンドの性質である、たまたま自分が管理する二つのエンドポイントで有効にする設定ではない。外部経路上のすべてのスイッチ、ルーター、プロバイダーの引き渡しがより大きなサイズに同意する必要があり、1,500バイトのホップが一つでもあれば、大きくしたばかりのパケットを黙って破棄する。ローカルインターフェースだけを上げるのは、トンネルが壊れたように見える一方でアンダーレイが静かに落とす、典型的な半分の変更である。
ip link set dev eth1 mtu 9000 ip link show dev eth1 ping -M do -s 8972 -c 2 198.51.100.10
インターフェースを変えたら、他を変える前に同じ経路を再プローブする。プローブがまだ失敗するなら, ip link set dev eth1 mtu 1500 で戻し、自分が所有していないリンクについてプロバイダーと論じるのではなくフラグメンテーションへ進む。
アンダーレイを大きくできないときはトンネルのフラグメンテーションを使う
内部パケットより下で対応しているフラグメンテーション機構があれば、複数の外部パケットで一つの内部パケットを運べる。対向のトンネルエンドポイントは元のパケットをスタックに渡す前にそれらを再構築する。 Community OpenVPN の UDP フラグメントオプション はその考え方の一実装であり、外部パケットの通常の IP フラグメンテーションとは同じものではない。両方のピアがその形式をサポートするバージョンを動かしている必要があり、データ経路も想定どおりでなければならない。OpenVPN 3 クライアントとカーネルアクセラレーションのデータチャネルは制限が異なるため、一方のクライアントで動くプロファイルが他方で失敗することがある。
openvpn --config client.ovpn --tun-mtu 1500 --fragment 1400 --verb 4
通常の外部フラグメンテーションももう一つの選択肢だが、弱い方である。IPv6 ルーターは転送パケットをまったくフラグメント化しないので、大きすぎる外部パケットは単に消え、送信側は該当する ICMPv6 メッセージが経路を生き延びた場合にだけそれを知る。フラグメントはフィルタリングと損失の増幅も招くので、私はこれを計画ではなくフォールバックとして扱う。
ストリームベースの外部キャリアは自身のバイトストリームを分割することでサイズの問題を回避し、再構築された内部パケットは依然として1,500バイトでよい。これは独自のコストを伴うトランスポートの決定であり、TCP over TCP のよく知られた挙動も含むので、MTU 論争の副産物ではなく意図的に選ぶべきである。
内部パケットが変わらず届くことを確認する
検証はハンドシェイクの成功ではない。 両端のトンネルインターフェースでキャプチャし, アプリケーションが実際に送ったパケットと対向側が受け取ったもののサイズと内容を比較する。
ip link show dev tun0 ping -M do -s 1472 -c 2 10.8.0.1 tcpdump -ni tun0 -c 5 'icmp and greater 1000'
キャプチャが対向側でフルサイズの内部パケットを示すなら、搬送の選択は機能しており、残る作業はそれを記録することである。トンネルが up と報告しているのに何も示さないなら、外部パケットはエンドポイント間のどこかで破棄されており、暗号設定ではなくプローブに戻ることになる。
チケットを閉じる前に三つのことを記録する。実測した外部予算、選んだ機構、内部パケットが生き残ったことを証明したコマンドである。次にこのトンネルを触る人は三つすべてを必要とし、どれも設定ファイルだけからは再構築できない。