エコー応答は返り、リモートデスクトップも動くのに、ブラウザは諦めるまで空白のページにとどまる。このパターンには二つの説明が当てはまるが、それらは一つの問題の変形ではない。サービスを一度も許可していない方針か、転送が大きくなると収まらなくなるパケットかである。エコー応答はどちらも否定しない。

最も小さい問いから最も大きい問いへ進み、各手順が実際に何を証明したかを書き留める。

エコー応答が答えるのははるかに小さい問い

エコー応答は、宛先の IP スタックがあなたの送信元からの ICMP 要求に応答したことを示す。必要なポートに TCP リスナーがあるか、方針がそのポートを許可しているか、宛先ホストがゲートウェイとは独立に通信をフィルタしているかは何も語らない。一方のサービスを許可するゲートウェイが別のサービスを落とすことはあり、両方の対象が ping に応答していても起こる。応答は一つのパケットと一つの方向についての一つの事実として読む。

他の何かを解釈する前に、宛先とサービスポートを確認する。試したアドレスとアプリが使うアドレスが別のレコードであることはあり、名前が二つのアドレスに解決されるとその可能性が高まる。

接続が始まったかどうかを調べる

すぐに拒否される接続はリスナーか方針の答えであり、何かが応答して否と言ったということだ。開いた後、データが動き始めたところで止まる接続はサイズを指す。ハンドシェイクをまったく完了しない接続はふつう方針かルーティングの問題で、拒否ではなくタイムアウトのように見える。

curl -v --max-time 10 https://internal.example/ -o /dev/null
ss -tn state established '( dport = :443 )'

MTU の設定に触れる前に、三つのうちどれを観察したかを記録する。拒否された接続を直そうとしてトンネルのサイズを変えると、その変更が無駄になり、本当の原因をしばらく隠してしまう。

示した数値でサイズを測る

負荷時に停止が現れたら、分割禁止ビットを立てて一つのパケットサイズを試し、結果が意味を持つように計算を示す。iputils を使う Linux では、1392 バイトのペイロードに 8 バイトの ICMP ヘッダーと 20 バイトの IPv4 ヘッダーを加えると、ちょうど 1420 バイトの内側パケットになる。この計算をチケットに書く。ゲートウェイに届くだけの素の ping はアプリについて何も証明しないからだ。

ping -4 -M do -s 1392 10.44.0.10
ping -4 -M do -s 1372 10.44.0.10

どちらのプローブも測定点であり、トンネルサイズの推奨ではない。経路のどこかで ICMP がフィルタされていれば、タイムアウトはサイズについて何も語らない。フィルタと大きすぎるパケットはクライアントから見て同じに見えるからだ。成功もまた、逆方向や別の宛先について何も語らない。

外側の経路を勘定に入れる

カプセル化は独自のヘッダーを加えるので、回線上のパケットはトンネル内で測ったパケットより大きい。両者の差が、機能する小さな要求と失敗する大きな要求を同時に成り立たせている。

IPv4 の経路 MTU 探索は、分割せずに転送できないパケットについてのフィードバックに依存し、IPv6 は Packet Too Big メッセージを使う。IPv4 の仕様がその仕組みを説明している。フィードバックをフィルタすると送信者が学ぶ能力が壊れ、決して収まらないパケットを再送し続けることになる。だからこそ機能する小さな要求と失敗する大きな要求がこれほど気楽に共存する。

一つの数値を変えてアプリを再テストする

トンネルの MTU を下げるか、TCP の最大セグメントサイズを制限し、プローブではなく元のアプリのテストを繰り返す。変更後に成功するプローブと、まだ固まるアプリは形の似た別の問題であり、アプリのテストだけが両者を区別する。

変更記録に計算を残す。測定したサイズ、前提としたオーバーヘッド、設定した値である。後で見直す人は、ping のスクリーンショットから推測をやり直す代わりに、その前提を確認できる。

試したすべてのサイズでアプリが動くなら、数値の調整をやめ、動くサービスと失敗するサービスを分けている方針を見る。

関連記事