運転中に VPN が再接続する:無線の切り替えか IP の変化か
基地局間のハンドオーバーは IP 経路をそのまま残すことがある。トンネルを移すクライアントと作り直すクライアントを比較し、運転ではなくネットワークのイベントを読む。
町の外れを走り抜けると通話が切れ、同じ瞬間に VPN のアイコンが消える。これを「基地局の切り替えがトンネルを殺した」と記録したくなる。起きたのは二つの別のことだが、そのうち塔に関係するのは一つだけである。無線のハンドオーバーは IP アドレス、既定ルート、セッションを完全に保ったままにできるが、本当のアドレス変化はそれに追随できないトンネルをすべて壊す。クライアントが二つ目の場合をどう扱うかを比べることが有用な練習になるのは、設計された挙動なのか不具合なのかが分かるからだ。
基地局の切り替えは必ずしもアドレスの変化ではない
移動体網は、事業者のモビリティアンカーが同じである限り、ハンドオーバーをまたいでパケットセッションを維持する。無線リンクは変わるがトンネルは気づかず、どのログにも再接続は現れないはずだ。都市内の移動ではこれが普通のケースである。
アドレスを変えるのは、アンカー間の移動、Wi-Fi から携帯網への切り替え、長時間の空白の後での事業者側のトンネル再確立だ。これらのイベントはパケットが運ぶ送信元アドレスを置き換え、VPN のピアは移動したピアを見ることになる。
実務上の結論は、移動は証拠にならないということだ。四十キロ走った端末が一つのアドレスを保っていた可能性もあり、止まっていた端末がネットワークの判断で二度アドレスを変えた可能性もある。イベントを記録することだけが両者を区別する方法だ。
二つの設計:トンネルを移すか、作り直すか
クライアントは、外側の送信元が変わったことをどれだけ重視するかで異なる。構築時のアドレスにトンネルを縛り、完全な再確立を求めるものもある。各パケットを独立に認証し、応答を送る先だけを更新するものもある。
| Mechanism | Behaviour after the source changes | What the user notices |
|---|---|---|
| WireGuard | Endpoint updated on the next authenticated packet | Usually nothing; the tunnel continues |
| IKEv2 with MOBIKE | Security association moves to the new address | Short pause, no re-authentication |
| OpenVPN over UDP with float | Peer address may change without a restart | Might survive, depending on timing |
| Client bound to one address | Session dies and is rebuilt | A visible reconnect and a new authentication |
上の行は多くの混乱した報告を説明する。WireGuard には壊すべきセッションがなく、各パケットはピアの索引を運び認証されるため、新しいアドレスから届いた正当なパケットは定義上そのピアのものであり、記録されたエンドポイントはそれに追随する。走行中ずっと「接続済み」と表示するクライアントは本当のことを言っている。
下の行も欠陥ではない。セッションを作り直すと現在のアドレスに対して認証をやり直すが、古いアドレスが他人のものになっている可能性があるとき、それこそが望む動作だ。
移動ではなくイベントを観察する
Android では接続サブシステムがネットワークの変化をイベントとして報告し、クライアントの挙動と関連づけるべきはそれであり、ダンプは冗長だが重要な部分は既定ネットワークとそのアドレスである。
adb shell dumpsys connectivity | grep -E 'NetworkAgentInfo|Default network'
adb shell ip -br addr show
adb logcat -b main -s Vpn:* | head -n 40
サーバー側にはローミングの場合の直接的な測定があり、WireGuard はピアごとに最後に認証したエンドポイントを保存するので、アドレスの変化は再接続ではなく値の変化として現れる。
sudo wg show wg0 endpoints
sudo wg show wg0 latest-handshakes
走行の前後でエンドポイントを比べる。アドレスとポートが変わっていなければ、トンネルは何もする必要がなく、再接続は別の場所、多くの場合アプリケーションから来たものだ。エンドポイントが変わり、しかもハンドシェイクの時刻が通常の鍵更新間隔に近いままなら、トンネルは再起動ではなく移動した。
再起動は見え方が違い、ハンドシェイクの時刻が再接続の瞬間にリセットされ、クライアントは静かな継続ではなく初期化の並びを記録する。
再接続が正しい挙動となるのはどんなときか
すべての再接続を故障とみなすと、死んだセッションを生かし続ける設定に導かれる。ネットワークが再割り当てしたためにアドレスが変わったピアは古い対応付けのトラフィックを受け続けるべきではなく、黙って続行するクライアントはアイコンが緑のままブラックホールへ送り続けることがある。
利用者の視点で二つの失敗を比べる。再接続の代償は数秒と再認証だ。古いトンネルの代償は、エラーも出さずに固まるアプリケーションであり、説明がはるかに難しく、「インターネットが壊れた」と報告される可能性がはるかに高い。
その下には方針の問いも隠れている。一方の経路を失ってから他方を確立するまでの空白の間に、直接トラフィックを送る状態に戻るクライアントがある。それを防ぐのは自動復旧とは別の制御であり、片方が得意で片方が苦手ということはあり得る。どちらを調整する前に、必要なのはどちらかを決めておくべきだ。
観察した順序を書き留める
役に立つ報告はイベントの出所、すなわち新しいアドレスを伴う既定ネットワークの変化、Wi-Fi から携帯網への切り替え、あるいはアドレス変化のまったくないハンドオーバーを名指しする。そのうえでクライアントが何をしたかを、記憶ではなくサーバー側の時刻で示す。
トンネルが移動したならそう書き、新しいエンドポイントの種別を記す。再確立されたなら、認証が一発で通ったかどうかと、空白がどれだけ続いたかを記す。この三つの事実が、健全なモバイル設計とネットワーク間で揺れるクライアントを分ける。
そして、端末のログが実際に裏づけない限り「基地局の切り替え」という表現は避ける。Android の接続に関するドキュメントは、可用性と既定ネットワークの変化を区別するコールバックを説明しており、報告に必要なのはまさにその区別だ。それ以外は運転についての物語にすぎない。