二つの失敗は利用者から見ると同じ言葉になる。サイトが動かない、という言葉だ。だが起きる層が違い、その違いが何を変えるべきかを決める。名前解決の失敗は接続が存在する前に止まる。パケットサイズの失敗は名前が解決されハンドシェイクが終わった後に起きるので、ページは読み込みを始めてから固まる。設定を探す前に段階を特定する。

別の層で起きる二つの失敗

解決は名前をアドレスに変える処理で、これが成功するまで接続の他の何も始まらない。経路 MTU の問題はもっと後に、あるリンクの上限より大きいパケットが破棄され、送信側にそれが伝わらないときに起きる。一方は検索であり、他方はあるサイズを超えたときだけ現れる配送の失敗である。

症状は道具なしで観察できる形で異なる。DNS の失敗は即座で一貫している。ブラウザはサーバーが見つからないと表示する。MTU の失敗は部分的だ。ページが始まり、一部の資源が届き、大きな応答やアップロードが止まる。

症状が部分的なら、DNS を見るのはやめる。

段階 1: そもそも名前は解決するか

アプリが使うのと同じホスト名で、その環境の検索道具を使う。社内の非公開名は内部のリゾルバを必要とすることがあり、ブラウザ独自の安全な DNS は OS のリゾルバと違う振る舞いをすることがあるので、同じ名前について両者が食い違うことがある。

OS が使うリゾルバに問い合わせ、それから比較する。

dig +short vpn.example.com
dig +short vpn.example.com @10.0.0.53

解決が失敗するなら、問題はその方針と到達性にある。比較のためだけに非公開名を任意の公開リゾルバへ送ってはいけない。比較そのものが、内部に保ちたかった名前を漏らすからだ。

段階 2: 転送がどこで止まるか

名前が解決し接続が始まったら、操作がどこで止まるかを記録する。表示された後に一つの資源で固まるページ、一定の地点で死ぬアップロード、小さな要求は通るのに決して終わらない大きなダウンロードは、いずれもサイズという形の症状だ。まったく始まらない応答は別の形をしている。

比較の間は端点とアプリの宛先を固定する。さもないと二つの変数を同時に測ることになる。この段階でも他の原因はあり得る。サービスの誤り、損失、フィルタの挙動、トンネルの再接続はいずれも停滞を生む。

再現できる停滞一つは、逸話十個より価値がある。

なぜ MTU はハンドシェイクの後にだけ害を与えるのか

TCP のハンドシェイクは小さなパケットを使うので、全サイズのセグメントを運べない経路でも成功する。失敗は、送信側が分割禁止ビットを付けた大きなパケットを送り、リンクがそれを捨て、上限を伝えるはずの ICMP メッセージがフィルタに飲まれて届かないときに現れる。送信側は同じサイズを再試行し、転送が止まる。

だから症状は偶然ではなくサイズ依存で再現性がある。これは、ホストへの ping が何も証明しない理由でもある。小さな ICMP エコーは全サイズの荷を運ばない経路を通り抜けられるからだ。可能なら経路の両端からサイズを測る。片方向にだけ現れる上限はトンネルの MTU ではなく経路の非対称だ。

推測するのではなく、サイズを明示的に測る。

ping -M do -s 1472 203.0.113.20
tracepath 203.0.113.20

一つの層を変え、それを証明する

名前については、リゾルバの方針を変えて同じ検索をやり直す。サイズについては、元の値を記録し戻せる準備をしたうえで MTU の手順 を使う。トンネルの実際の MTU を知らずに MSS を絞ると、一つの停滞を別の停滞と交換するだけだからだ。

いくつかの設定を変えた後に一度だけ読み込めたページは、何が直したのかを示さない。一つだけを変え、同じ試験をやり直し、その結果を最初に記録した失敗段階の隣に置く。

その記録こそが、DNS とパケットサイズと認証を、誰にも説明できない恒久的な回避策の山にしないためのものだ。生の IP で試すのは TLS の身元を変えてしまう近道の良い例であり、比較を通すために証明書の検証を切るのは診断ではない。

関連記事