パッケージの除外はブロックではなくルーティングの指示なので、VPN 接続後に読み込まれるページは想定どおりであり、障害の証拠ではありません。除外はアプリをブロックするのではなくトンネルから外し、その通信は通常のネットワークが運びます。ここでは二つの別個のポリシーが出会っています:一方はプロセスを選び、他方は宛先を選びます。この順序で読むと、接続アイコンと動作するアプリが矛盾ではない理由が分かります。

除外がネットワークを開いたままにする理由

VpnService.Builder は許可リストか拒否リストのどちらか一方だけを受け取り、両方は受け取りません。トンネルを通るのは許可リストにあるパッケージだけです。拒否リストはこれを反転させます。一覧にあるものを除くすべてのパッケージがトンネルを使い、一覧にあるものは物理経路を保ちます。許可リストでは一覧にないパッケージもトンネルの外にあるため、このモードではほとんどのアプリにとって除外が通常の状態です。

つまりローカルの拒否エントリはファイアウォール規則ではなくルーティングの判断です。要件がアプリをホストに到達させないことなら、トンネルがそのアプリを覆い、サーバーまたはローカルポリシーが通信を拒否する必要があります。アプリをトンネルから外すと変わるのは、どのインターフェースがそのパケットを運ぶかだけです。

Play Store の例はよくある意図的なものです。ストアのパッケージを除外すると、VPN の出口が転送を妨げるときにダウンロードが下位の接続を使えます。これは除外がブロックではなく迂回を意味することを示しています。

一つのプロファイル、一つのリスト

両方の呼び出しを使うとビルダーは例外を投げるので、目の前のプロファイルは許可リストか拒否リストのどちらかです。この一つの事実が、以降のあらゆる観察の読み方を決めます。ルーティングテーブルの前にコードか管理対象構成を確認してください。リストが出力の残りの意味を決めるからです。ハイブリッドなプロファイルは観察できる状態ではありません。

この区別は、新しくインストールしたアプリの挙動も予測します。許可リストでは誰かが追加するまで外に留まり、拒否リストでは既定でトンネルに入ります。

管理対象構成は同じ選択を別のキー名で公開し、コンソールによってはリストではなくアプリ別 VPN モードと呼びます。それでも挙動はこの二つの呼び出しに還元されるので、ラベルを信じるのではなく設定をパッケージリストまでたどってください。ラベルとリストが食い違う場合はリストが優先です。

UID ルールをたどってトンネルのテーブルへ

Android はアプリごとに独自の Linux ユーザー ID を与え、VPN サービスは UID の範囲に一致するポリシールールを導入します。一致した通信は、既定ルートが tun デバイスを指すルーティングテーブルへ送られます。テーブル番号は VPN インスタンスごとに割り当てられるため、再接続後や二つ目の VPN プロファイル作成後に変わります。

ルールの出力が地図です。各行は参照テーブルを名指しし、そのテーブルが一致するパケットをトンネルに入れるかを決める既定ルートを保持します。

adb shell ip rule show
adb shell ip route show table all
adb shell cmd package list packages -U | grep <package>

UID を得るためにまず三番目のコマンドを実行し、その範囲に UID が含まれるルールを探します。そのルールはテーブル番号を指し、その番号を付けて ip route show table <n>を実行すると、tun デバイス経由の既定ルートがあるかどうかが分かります。テーブルに既定ルートがなければ、アプリは選択されているのに経路がないという、別の障害です。

これらのコマンドにはデバッグ可能なビルドか、adb shell がネットワーク状態を読める端末が必要です。製品版の端末ではパッケージマネージャーは応答しますが、ルーティングの検査は拒否されることがあるので、取れる範囲を記録し、残りは未確認として扱ってください。

ルートが主張するのはプレフィックスであり、アプリではありません

Builder.addRoute はトンネルに宛先プレフィックスを要求します。10.0.0.0/8だけを追加するプロファイルは、そのプレフィックスをトンネルへ送り、他のすべての宛先を物理経路に残します。これは通常の分割トンネリングであり、ルールがどのアプリを選んだかとは独立です。

サーバーから配信される構成も同じモデルを映します。個々のルート配信はプレフィックスを追加し、redirect-gateway 指令は既定ルートを置き換えてトンネルが覆うアプリのすべてを捕捉します。その指令を外すと、端末側を何も変えずに、動作中のトンネルが一つのサブネットまで縮むことがあります。

異常なゲートウェイやメトリック修飾子を持つ配信ルートも、インストールに失敗することがあります。単純なプレフィックス形式を選び、転送と NAT はサーバーに任せてください。

設定を変える前に交差を読む

トンネルが運ぶのは、覆われたプロセスと要求された宛先の交差です。公開されたプレフィックスの外のアドレスを求めるアプリは物理ネットワークから出ます。拒否されたパッケージは、そのプレフィックス内のアドレスを求めても外に留まります。どちらも不具合ではなく、二つのポリシーがそれぞれの仕事をしているだけです。

アプリ別 VPN は、関連付けられたアプリを接続なしのままにすることもあります。on-demand が切れていてトンネルが落ちていると、アプリはアプリ別 VPN に結び付いたままで代替経路がなく、ポリシーの状態ではなく壊れたアプリのように見えます。on-demand を有効にするか、管理を通じて関連付けを外せば変わります。

LayerWhat it selectsWhere to lookTypical mismatch
Package listProcessesBuilder calls or managed configurationApp excluded but expected to be blocked
UID policy ruleWhich table a UID usesip rule showTunnel icon on, app still on Wi-Fi
Routing tableDestinations for matched trafficip route show table <n>Covered app reaches only one subnet
Server pushPrefixes offered to the clientServer route configurationTunnel shrinks after a server edit

一度に一つの軸を診断します。まず許可か拒否かを確認し、次に導入済みの UID ルールとテーブルを読み、最後に同じ宛先に対して二つ目のアプリを試します。二つ目のアプリは、一つの要求の中でプロセスの選択と宛先の選択を切り分けます。

結果をアプリ、宛先、テーブル番号として書き留めます。次の変更が守るべきは、まさにこの組です。

関連記事