一つのアプリをVPN経由のみに強制できるmacOSツールはどれか。
VPN限定の境界には経路と拒否の両方が必要です。アプリ別プロファイル、プロキシ、フィルタ、PFを比較し、重要な一つのアプリをテストします。
要件文書の一行、「このアプリはVPNを使えて、それ以外は使えない」は、どの単一スイッチも提供しない二つの仕組みを静かに求めている。通信には意図したトンネルを通る経路が必要であり、直接出ていく通信は拒否されなければならない。片方をうまくこなし、もう片方をまったくしないツールはよくある。だから、何かがブロックできるかだけを問う比較は、質問の半分に自信をもって答えることになる。まず境界を書き出し、次にその両半分を覆う構成要素を選ぶ。
一つの文に隠れた二つの要件
誘導とは、接続をトンネルまたはプロキシに入れる部分である。拒否とは、同じ接続が他のどの経路からも出ていかないようにする部分である。実装する構成要素は異なり、失敗の仕方も異なり、ある製品が一方に優れていても他方については何も語らないことがある。
| Approach | Steers traffic | Refuses direct egress | Knows the app identity |
|---|---|---|---|
| Per-app VPN profile | Yes, for the apps it names | Only if a filter or firewall also blocks | Yes, within its own rules |
| Application proxy setting | Partly, for requests that honour it | No | No |
| Content filter | No | Yes | Yes, if the filter is written that way |
| Local PF ruleset | No | Yes, by address and port | Not reliably |
表はランキングではなくチェックリストとして読んでほしい。中央の二列を埋める行は一つもなく、それらを覆う行は協調する二つの構成要素である。一方が経路を、他方が拒否を持つ。識別の列が別の理由で重要なのは、アプリを名指しできないルールはそのアプリについてのルールを強制できないからだ。何を配備するにしても三つすべてに答えなければならず、そうでなければ要件文書の境界はマシン上の境界ではない。
誘導だけでは出口が残る
アプリケーションプロキシの設定は、拒否を伴わない誘導の最も明快な例である。システムプロキシに従うアプリの要求は誘導できるが、それ以外は何も覆わない。ヘルパープロセス、アップデータ、バックグラウンドサービス、別のプロトコルは、その設定を一度も読むことなく独自の経路を通りうる。したがって一つの画面でSOCKSエンドポイントを選んでも、アプリに対する直接出口禁止のポリシーにはならない。要件がアプリ全体についてなら、ルールが実際にどの構成要素を識別するのかを問うべきだ。
アプリ別VPNプロファイルはプロキシよりもうまく誘導する。どのアプリがトンネルに入るかをプラットフォームが決めるからだ 各アプリが自分で決めるのではなく。それでも何も拒否しない。プロファイルは経路を与え、それに合わない通信は通常の経路を通る。まさにその隙間が二つ目の構成要素の出番であり、一つのスイッチに見える製品がたいてい二つである理由でもある。
拒否だけではアプリが壊れる
Appleのコンテンツフィルタに関するドキュメントは、ネットワークスタックを通過する通信に対する許可か遮断かの判定を説明している。その判定はトンネルでもプロキシ接続でもない。何かが続行できるかどうかを決めるのであって、どこへ行くかを決めるのではない。フィルタ単体は拒否を完璧に強制し、アプリを使い物にならなくする。ログはきれいで、説明は何もない。フィルタの判定は接続を止められてもトンネルは決して与えない。だから誘導と組み合わせることが設計上の決定であり、任意の追加ではない。
ローカルで管理するPFルールセットは、そのスペクトルの反対の端に位置する。管理者が所有するマシンでの正当なサポート判断であり、配布できる製品の土台に自動的になるわけではない。ルールセットを所有する者は、他のファイアウォール利用者との相互作用、更新の経路、ルールが誤っているときの復旧も所有するからだ。製品にPFを加えてもその所有権の問いは消えず、むしろ定義される。
配備が、そのルールが明日も存在するかを決める
AppleプラットフォームでのNetwork Extensionの配備方法は、プロバイダの種類、パッケージング、目の前のOSバージョンによって変わる。macOSのアプリ拡張はユーザーコンテキストで動き、そのユーザーがログアウトすると終わる。一方、システム拡張はセッションに依存しないグローバルなコンテキストを持つ。保護がログアウトを越えて存続しなければならないなら、その違いは脚注ではなく設計そのものである。振る舞いを約束する前に配備経路を確認すべきだ。同じコードでも、出荷する拡張の種類によって着地点が変わる。
ソースの入手可能性は適用とは別の問題である。リポジトリを読めば何かがどう実装されているかは分かるが、インストール済みのバイナリがこのマシンで何をしてよいかは分からない。署名、インストール、認可は依然として適用される。そして廃れたカーネル拡張やライブラリ注入の小技を前提にした手順は、かつてどれほどうまく動いたとしても、別のプラットフォームと別のリスク姿勢を語っている。
アプリを名指しする受け入れケース
アプリが自発的に行う動作を一つ選び、到達すべきアドレスとそれがIPv4かIPv6かを記録し、承認されたトンネルなしの状態で同じ動作を繰り返す。二回目の実行は、静かな直接の再試行ではなく、宣言された拒否を生まなければならない。それが人々が未指定のままにする半分であり、拒否がそもそも存在することを証明する唯一の半分である。まずトンネルが利用できる状態で実行し、二つの結果の差が失われたトンネルだけに由来するようにする。
次に、要件が挙げる遷移をたどる。アプリの再起動、ヘルパーの発火、トンネルの再接続、マシンのネットワーク変更、該当する場合はログアウトや再起動である。ブラウザの公開IPページは別のアプリのソケットのテストではないので、これの代わりにはならない。サポートされる配備がアプリの実際の振る舞いを覆わない場合、明示的なゲートウェイを持ち代替の出口がない承認済みの隔離環境は、独自の管理コストを伴う封じ込めの判断であり、チェックボックスの代替ではない。
最後に四つの項目を書き出す。アプリがどの構成要素から成るか、誘導を誰が持つか、拒否を誰が持つか、そしてルールがなお有効でなければならない状態である。公開リポジトリは選択基準の一つになりうるが、四つのうちの一つではなく、その項目こそが、あるツールがネットワーク要件を満たすかどうかを決める。