SSH は接続でき、プロンプトも出るのに、コマンドがまとまった量を返した瞬間にセッションが死にます。エコーはしばらく通り、やがて接続がタイムアウトしますが、クライアント側ではトンネルが上がったままに見えます。データが来るまでは健全なセッションは、SSH の不具合ではなくサイズの上限に当たっているのが普通です。以下の確認は、最も安上がりな説明から先に潰す順に並べてあります。

プロファイルを触る前に障害の形を読む

小さいパケットは通り、満杯のパケットは通りません。プロンプトやバナー、キー一打は簡単に収まりますが、ディレクトリ一覧やダウンロード、貼り付けたブロックは収まりません。挙動が変わるそのサイズが手がかりであって、SSH が関わっているという事実ではありません。

仕組みは 経路 MTU の探索で、これはフィードバックに依存します. TCP はセグメント長を選び、途中のルーターがその結果のパケットを転送できないときは ICMP メッセージで知らせることになっています。カプセル化で外側のパケットは内側より大きくなるため、トンネル内で使えるサイズは常に物理リンクを下回ります。その ICMP メッセージをどこかで濾過すると、送信側は補正を永遠に受け取らず、満杯のセグメントを送り続け、外側のパケットは通知なく捨てられます。

両側から上限を測る

どちらかを変える前に、トンネルの MTU と物理リンクを比べてください。物理の値をそのまま写したトンネルなら、食い違いがどこにあるかはすでに示されています。

トンネルの内側から分割禁止の要求で試し、応答が戻るまでペイロードを下げていきます。サイズ引数はペイロードだけを数えるので、通る値は常にインターフェース MTU を下回ります。インターフェースの数値が必要ならヘッダー分を足し戻してください。

ip link show tun0
ping -M do -s 1380 10.9.0.1

トンネルの外からサーバーの公開アドレスに対して同じ測定を繰り返します。そこで大きな測定も失敗するなら、上限はサーバーまでの経路にあり、トンネルの設定では動きません。この比較をしておけば、そもそも原因でなかったクライアントを調整せずに済みます。設定ファイルを開く前に、両方の結果を書き留めてください。

mssfix と fragment は別の仕事をする

mssfix は、トンネル内の TCP 接続がハンドシェイク時に告知するセグメント長を制限します。SSH や HTTPS、ファイルコピーに効く正しいレバーで、だから設定した途端に固まりが消えることが多いのです。UDP のペイロードには一切触れません。

UDP サービスも載せているトンネルは、SSH を直した後も失敗し続けることがあり、その結果は一つの設定で全部まかなえると考える人を必ず混乱させます。

fragment はもう一つの仕組みで、別の道具です。カプセル化の前に大きすぎるパケットを分割し、UDP 転送にだけ適用され、データグラムごとの負荷を加え、壊れた探索に対する最後の手段として文書化されています。どちらの設定もトンネルを終端する相手側で一致していなければなりません。片側が制限し他方が分割すると、ログの警告と、ファイルからは誰にも予測できない挙動が生まれます。

インターフェース MTU を下げるのは乱暴な選択肢

両端でインターフェース MTU を下げるのは乱暴な道具です。内側の送信者すべてに小さい数値を伝えるので効きますが、その代償を必要とする TCP フローではなく全トラフィックに負わせます。

トンネルが制限できないトラフィックを運ぶとき、あるいはクライアントがプロファイルを管理できない機器のときに選びます。対称に適用し、値はプロファイルの脇に記録してください。半分だけ適用した変更は、直ったように見えるぶん、何もしないより悪いのです。

固まった転送で再試験する

設定を読み込ませるために再接続し、新しい接続を開いて、凍りついたコマンドを繰り返します。セグメント長はハンドシェイク時に決まるので、再接続を生き延びたセッションはまだ古い値を引きずっています。ここで ping が弱い試験なのは、失敗の本質が小さいパケットは通ることにあるからです。壊れた一覧表示やダウンロード、貼り付けを使ってください。

より小さいサイズでも固まるなら、フローを期限切れにするステートフルなファイアウォール、重複したアドレス、再接続で動く経路など、別の場所を見てください。失敗した測定サイズと変えた設定を記録すれば、その組が次の報告を役に立つものにします。

関連記事