二つの VPN クライアントは並行して動かせますが、それぞれの kill switch が一つのポリシーに統合されることはありません。各クライアントは自分のトンネル用のルールを入れるだけで、相手の存在を知りません。私が遭遇したのは、仕事用クライアントを先につないだ場合です。二つ目のアプリはハンドシェイクを終えられず、„Connecting“ のまま十分止まり、最初のトンネルが黙ってすべてを運んでいました。二つ目のアプリが保護されるかどうかは三つの条件で決まり、両方のアイコンが「接続済み」と出るかどうかではありません。

kill switch が実際に及ぶ範囲

OS には単一の kill switch フラグというものはありません。対応をうたうクライアントはルール一式を導入します。自分のトンネルから出ないものはすべて破棄し、トンネルが消えたら fail closed になることが多い、というものです。Linux では通常 nftables か iptables のチェーン、Windows では Windows Filtering Platform のフィルター群、Android と iOS ではトンネルサービス自身のルーティングに、VPN なしの接続を止めるシステム設定が加わります。Android VPN ガイドにはこのサービスモデルの説明があります。プラットフォーム側の見方を知りたい場合にどうぞ。

重要なのは適用範囲のほうです。「wg0 出力インターフェースのパケットだけを許可する」といったルールは、二本目のトンネルがあるかどうかを気にしません。別のクライアントが wg1 を立ち上げると、一つ目のクライアントのルールはそのパケットを普通のトラフィックとして扱います。たいていは破棄され、ときどき通ります。いずれにせよ決めているのは一つ目のクライアントで、二つ目のアプリが待っていることなど知りません。

誰が守られるかを決める三つの条件

すべての組み合わせを数え上げる必要はありません。三つの問いで数分のうちに決まります。

  1. そもそもプラットフォームが二本目のトンネルを許すか。多くの Android 端末と iPhone は、ユーザープロファイルごとに有効な VPN サービスを一つしか受け付けません。したがって二つ目のアプリはトンネルを持てず、何も強制できません。得られるのは一つのポリシーだけで、場所を取ったほうのアプリのものです。
  2. デフォルトルートを所有しているのはどのプロセスか。Windows、macOS、Linux はどれも二本のトンネルを平気で載せます。デフォルトルートは、最後に設定したクライアント、またはメトリックが良いほうのものになり、もう一方は接続したまま待機します。Linux では wg-quick のデフォルトルートモードが、専用テーブルと fwmark ルールを使うポリシールーティングを採用するため、二本目の wg-quick トンネルは一本目を置き換えるのではなく、競合するルールを追加します。
  3. 二つ目のクライアントは自分のサーバーに届くか。一つ目の kill switch がデフォルト拒否なら、二つ目のアプリの外側エンドポイントは、ただの破棄される宛先です。静かに再試行を続け、エラーを報告しません。

サポートスレッド向けの短い版です:

SetupWhat you actually get
Second client cannot hold a tunnelOne active policy; the other app only reports that it is waiting
Both tunnels up, second took the default routeThe first kill switch blocks traffic it never meant to touch; the connection dies, or leaks if its rules are broad
First kill switch allows only its own endpoint and interfaceSecond client never connects; first tunnel unaffected
Both up, DNS written by whichever client ran lastName resolution breaks for one side when either tunnel drops

そのうち二行はトレイのアイコンからは同じに見えるので、ここではアイコンが最悪の証拠になります。

最初に壊れるものと、その見え方

もう一方が健全なのに片方が „Connecting“ で止まるのは、ほぼ常にエンドポイントの枯渇です。動いている kill switch が、二つ目のクライアントから自分のサーバーへのハンドシェイクを捨てています。安く確かめるには、一つ目のクライアントのブロックルールを一回分だけ止めてみてください。二つ目がすぐつながれば答えは出ています。

二つ目は DNS です。クライアントは自分のインターフェース用にリゾルバー設定を入れ、なかにはグローバルなリストをそのまま上書きするものもあります。両方のトンネルが上がっていると、名前解決の問い合わせが片側から出て、リゾルバーはもう片側に属している、という状態が起きます。どちらかのアプリを切断すると、残ったほうは到達できないネームサーバーを抱えたままになります。ページは一分ほど止まってからまた解決し、VPN は接続済みの表示のままです。

三つ目はルートの揺れです。再接続でデフォルトルートが並べ替えられ、インターフェースに縛られた kill switch はそれに追随しません。さっきまでトンネルの中にあった通信が、いまは破棄ルールに一致する。ユーザーから見ると、VPN がときどき勝手に止まるように見えます。

どのポリシーが実際に効いているかを確かめる

無害な通信で試して、失いたくないものは使わないでください。

Linux では、どちらが勝っているのか、ファイアウォールが何に紐づいているのかをカーネルに聞きます。ip -4 route show default は出口を持つトンネルを示します。ip rule show はポリシールーティングが効いているかを見せます。sudo nft list ruleset | grep -n oifname は破棄がインターフェース名に縛られているのか、マークなのか、出力チェーン全体なのかを示します。

Windows では同じ話がルートメトリックとフィルター一覧にあります。Get-NetRoute -DestinationPrefix "0.0.0.0/0" | Sort-Object RouteMetric と Get-NetFirewallRule -Enabled True | Where-Object DisplayName -match "VPN" です。macOS なら netstat -rn -f inet | head -5 と scutil --dns | head -20 です。

そのあと、多くの人が飛ばす手順をやってください。トンネルをわざと止めて、失敗するはずの通信が本当に失敗するかを確かめるのです。接続済みのアイコンは UI の状態であって、強制ではありません。

二つのクライアントが間違った設計になる場合

二つ目のアプリの背後にある要件が「もっと保護がほしい」だけなら、それは外してください。相互作用する二つのブロックポリシーは一つより予測しにくく、再接続のたびに、どちらのベンダーも試していない状態に落ちる可能性があります。

本当に連鎖が必要なら、たとえば商用ホップ経由で企業ゲートウェイに届く構成なら、強制ポイントが一つだけの設計を選んでください。通常それは、その連鎖を支えるルーターか単一のクライアントであって、同じデフォルトルートを奪い合う二つのデスクトップアプリではありません。管理された端末では、認められたクライアントを残し、それ以外はスコープ外として扱ってください。トレイに何を表示していても同じです。

両方を残す前のチェックリスト

上から順に進めて、最初に失敗した項目を直してください。

  • デフォルトルートとリゾルバーを所有しているクライアントがちょうど一つであることを確認する。
  • 二つ目のクライアントを上げておきたいなら、そのサーバーのエンドポイントを明示的に許可し、クライアントの更新のたびに確認し直す。
  • どちらかのトンネルが落ちたときの期待結果を書き出し、そのケースだけを試す。
  • 再起動後の失敗経路を確認する。起動順が変わるときは特に。
  • 管理されたプロファイルでは、何かを追加する前に止まって所有者に聞く。

三番目の手順が失敗したら、正直な答えは「ポリシーを与えているクライアントは一つだけ」です。どちらを信頼するかを決めて、もう一方は手放してください。

関連記事