同じサーバー上の他の端末はすべて動作しているのに、一台のノートPCだけがトンネル経由のアップロードで止まる。このパターンはサーバー設定ではなく一本の経路を指しており、mssfixの疑問へのいつもの入り口である。このオプションが助けになるのは、実際に書き換えるTCP接続だけだ。その範囲を知っていれば、一台のクライアントを救うために動作中のサーバーを変えることはない。

このオプションが書き換えるもの

mssfixはトンネルを通るTCPハンドシェイクで告知される最大セグメントサイズを編集し、送信側がカプセル化の予算に収まるセグメントを選ぶようにする。作用するのはハンドシェイクなので、変更前に開かれた接続は交渉済みの値を保つ。

UDPデータグラムは小さくせず、トンネルのMTUも設定しない。同じ症状を生む問題は二つあり、経路の上限を無視するTCP送信側と、サイズにかかわらず大きなパケットを黙って捨てる経路だ。mssfixが扱うのは前者だけで、後者には何もしない。

この区別が、期待外れの実験を説明する。ブラックホールの経路で小さい値を設定しても、セグメントサイズは変わるがその後の破棄は変わらないため、転送は別の地点で失敗する。

範囲はトンネル内のTCP

書き換えられるのはTCPトラフィックだけだ。QUICセッション、ゲーム、大きなUDPデータグラムを送るアプリは自分のパケットサイズを保ち、そうした転送が止まっているなら、修正はむしろトンネルや経路のMTU側にある。TCPオプションに手を伸ばす前に、失敗している転送がどのプロトコルを使うかを読むべきで、誤った層には独自の修正がある。

方向も重要だ。クライアント側の設定はそのクライアントがトンネルへ送るトラフィックに効き、サーバー側はクライアント向けに転送するフローを覆う。受信のダウンロードだけが止まるなら、クライアント側の値がすべてではない。

数値とキーワードは移植できない

OpenVPN 2.6のコミュニティ版は値の後に任意のキーワードを受け付ける。mtuを付けると、数値はIPとUDPのヘッダーを含む外側のパケットサイズを表し、付けなければ、引数は別の計算規約に従う。したがって、バージョン間でコピーした行は同じパケット予算を表さない。別リリース向けのチュートリアルではなく、実際に動かしているビルドに付属するマニュアルページを確認すること。

構文は次のとおり:

mssfix 1400 mtu

1400はプレースホルダーとして扱い、自分の経路への推奨値とは考えないこと。値は計測した経路と実際に使うカプセル化から導き、古いバージョンや別実装のクライアントがキーワードを拒否したり別解釈したりする可能性を忘れないこと。

まず一台のクライアントで確認する

何かを変える前に、失敗しているマシンから経路を計測する。断片化せずに経路が運べるペイロードが、探している数値だ:

ping -M do -s 1472 10.8.0.1
ping -M do -s 1400 10.8.0.1

最初のプローブは、28バイトのヘッダーを足すと1500バイトのパケットに収まる。断片化エラーで失敗し、小さい方が成功するなら、使えるサイズはその間のどこかにあり、トンネルのオーバーヘッドは上から差し引かれる。

次に、止まった転送を新しい接続で繰り返して比較する。一台だけ改善し他が影響を受けないなら、問題の範囲を特定できた。すべてのクライアントが止まるなら、見直すべきはサーバー側の値だ。どちらの結果も、失敗した経路に一度も入っていないハードウェアを変更する理由にはならない。

関連記事