アプリ単位のキルスイッチは慎重な選択に聞こえる——トンネルが切れたときネットワークを失うのは業務クライアントだけで、ほかは動き続ける。ところが、個人用ブラウザはページを読み込んでしまい、同じスイートに同梱された同期ヘルパーは再試行を続け、キャッシュされた名前はトンネルを一度も通らないアドレスに解決されていた、と誰かが気づく。機能につけられたラベルと、それが実際に保護する接続の集合は別物だ。まず保護対象の集合を決めるべきで、その集合がアプリ単位の適用か端末全体のロックダウンかという正直な説明を決める。

ラベルではなく集合から始める

アプリ単位のポリシーは選択したアプリを保護する。端末のロックダウンはより広いネットワーク境界を狙い、通常はローカル印刷、管理トラフィック、キャプティブポータル向けの文書化された例外を伴う。どちらのラベルも、次の三つの問いに答えられるまで完全ではない—— 除外されたアプリはどうなるか、そのアプリが起動するヘルパーはどうなるか、保護が利用できない間に開かれた接続はどうなるか。

クライアントの設定に触れる前に、その答えを書き出す。要件が「この給与計算クライアントはトンネル外でインターネットと通信してはならず、私のブラウザは通信してよい」なら、集合は小さくアプリ単位の適用が合う。要件が「この端末では更新サービスを除き、何も保護なしでインターネットに届いてはならない」なら、アプリ単位のポリシーでは実現できない——名前を挙げなかったアプリこそが問題だからだ。

アプリ単位の適用は識別子で照合し、プログラム名では照合しない

Android はパッケージを通じてアプリ単位の VPN を提供し、その VpnService のドキュメント が常時接続とブロックとの関係を説明している。iOS は管理プロファイルを通じてアプリ単位の VPN を構成し、アプリまたはドメインで照合する。Windows と Linux にはプロセス単位のルートがまったくないため、同じ考え方はプログラムに限定したファイアウォール規則や、所有ユーザーに一致する規則で近似される。

境界は識別子であり、識別子は簡単にすり抜けられる。URL をシステムのブラウザに渡すアプリや、文書をビューアで開くアプリは、ポリシーが一度も名指ししなかったプロセスへ移る。 切断時に終了するオプションもパケットフィルタではない——設定したアプリを殺すだけで、子プロセス、キューのワーカー、ブラウザのタブは既存のソケットを生かし続けられる。

ロックダウンはアプリ単位のポリシーが見えないものを覆う

端末全体のロックダウンは選択を奪う。トンネルに属さないすべての外向きパケットが破棄され、アプリのポリシーが知らなかったプロセスのトラフィックも含まれる。Android では常時接続 VPN と接続ブロック設定の組み合わせで、適用はクライアントのウィンドウではなくシステムで行われる。デスクトップでは常設のファイアウォール規則か、到達不能なゲートウェイに向けた既定ルートになる。

代償はほかがすべて止まることで、例外は後付けではなく設計の一部になる。ローカルプリンタ、サービス検出、キャプティブポータルのログイン、管理エージェント、OS の更新は、それぞれ文書化された穴を必要とする——どれもトンネルが落ちている間に開いたままになる経路だからだ。ロックダウンの強さは、その一覧で最も短い項目と同じでしかない。

DNS、IPv6、バックグラウンドのヘルパーが漏れを隠す

保護されたアプリが名前を解決できないことは、キャッシュされた応答や直接 IP のトラフィックが遮断されている証拠にならない。リゾルバがトンネル外からまだ到達できるなら、名前は解決され、接続は失敗する——これは動いているキルスイッチに見えて、そうではない。さらに悪いことに、キャッシュされたレコードがトンネルの運ばないアドレスを指すことがあり、アプリが VPN エラーを報告する間に接続は直接外へ出てしまう。

IPv6 は、それを動かすすべてのプラットフォームで独自の規則を必要とする——v4 の破棄規則は v6 のルートを覆わないからだ。モバイルでは、プライベート DNS の設定が名前解決を暗号化されたチャネルへ移すことがあり、端末のポリシーはそれを検査しない。バックグラウンドのヘルパーはデスクトップの常連の犯人だ——トレイのアップデータや同期プロセスは VPN クライアントより先に起動して独自の接続を保つため、変わったルートを決して見ない。

三つのアプリと二つの遷移を試す

TestWhat it proves
Included app, by name and by direct IPthe policy is applied, not just the resolver
Excluded app, same checksthe exclusion is intentional and documented
Helper or updater processnothing inherited an older route
Tunnel drop, then Wi-Fi to cellularthe block survives the transition

各行を二回、一回はホスト名で、一回はリテラルのアドレスで実行し、ネットワークが提供するなら IPv6 でもう一回実行する。合格とは、含まれるアプリが止まり、除外したアプリが書いたとおりに振る舞い、ヘルパーが抜け出さなかったことを意味する。許容できると決めた直接の挙動を記録しておけば、次の管理者が意図的な例外と障害を区別できる。

次に、アプリと条件を名指しする一文で結果を説明する——たとえば、給与計算クライアントはトンネル外のルートを持たず、ブラウザは設計上直接で、トンネルが落ちればほかはすべて止まる、という具合だ。その文が書きにくいなら、ポリシーはまだ互いに戦う二つのポリシーである。

関連記事