Android の L2TP 自動化: スクリプトは要求できても、構築はできない
shell のルート設定は Android で L2TP/IPsec を起動しません。IPsec、L2TP、PPP、プラットフォームのポリシーがそれぞれ一部を担うため、何が制御できるかを見極めてください。
俗説では、L2TP は Android で shell スクリプトが起動できるもう一つの対象だと言われます。ルートを追加し、古いサービスを呼べば終わり、というわけです。そうはなりません。トンネルがパケットを運ぶ前に、四つの異なる層が合意する必要があるからです。IPsec 層が経路を保護し、L2TP がセッションを運び、PPP がリンクを交渉し、Android がその結果を、ルーティングできる VPN として登録しなければなりません。コピーしたコマンドで二度試されたのを見ましたが、どちらも経路だけが存在し、何も暗号化されていませんでした。
ルート変更が実際に果たすこと
ルートの追加は、パケットが次にどこへ行くかを決めます。セキュリティ アソシエーションを交渉せず、L2TP セッションを開かず、アドレス、ピア、DNS 設定を生み出す PPP 交換も実行しません。端末で目に見える結果は、誤った経路から出ていくトラフィック、あるいは出て行って途絶えるトラフィックで、どこにもトンネルの状態はありません。
古いリリースからコピーしたサービス呼び出しも同じです。Android の内部 VPN 配管は公開された自動化 API ではなく、別バージョンの番号付きトランザクションは別の操作に当たったり、スクリプトにない権限を要求したりします。パスワードを運ぶ自動化は、推測した内部引数に依存すべきではありません。失敗の形が、無言の no-op か、誰も片付けない半端なプロファイルだからです。
四つの所有者、スクリプトはそのどれでもない
順に見ていきます。IPsec は保護された経路を確立して維持し、ピアを認証します。L2TP はその上でセッションを運び、この階層化があるからこそ標準は両者を一つのプロトコルではなく別々の仕組みとして扱います。その内側で PPP がクライアントの使うリンク パラメータを交渉します。次に Android がプラットフォーム側を担います。登録された VPN インターフェース、アプリごとの範囲、always-on 状態、そしてアプリが終了したときの挙動を決めるライフサイクルです。
スクリプトが見られるのはその最後の層だけで、しかも普通は間接的にです。そのクライアントが文書化された制御を公開していれば接続を要求でき、後からインターフェースの状態を監視できます。下の三層を置き換えることはできず、未登録のインターフェースをプラットフォームに VPN として扱わせることもできません。
デーモンも近道にならない理由
端末で特権 Linux デーモンを起動すると、欠けていた部品のように見えますし、実際にトンネルが立ち上がることもよくあります。ただし、そのトンネルを Android に登録はしません。インターフェースはカーネル内に存在しますが、プラットフォームの VPN 選択、アプリごとのルーティング、always-on ポリシー、ライフサイクルはそれを知りません。デーモン自身のルートと DNS の変更は、同じテーブルをめぐってネットワーク マネージャーと競合します。
結果は、デーモンのトラフィックには効き、あなたが気にしていたアプリには不思議と効かない接続か、システムがネットワークを再評価するまで生き残る接続です。どちらもプラットフォームのバグではありません。ソケットを所有することと、VPN 機能を所有することの境界です。
サポートされる経路の形
組織が Android 自身が用意するプロファイルへ移行できるなら、プラットフォームの道が正直です。API 30 以降、VpnManager はアプリによるプラットフォーム VPN プロファイルの提供と制御をサポートし、呼び出し元アプリに紐づく承認フローがあります。これは L2TP の変換器ではありません。IKEv2 向けに提供するプロファイル モデルは既存の L2TP 設定を変換せず、プロトコルの移行は改名ではなく移行です。ID、ルート、プライベート DNS、アクセス許可は意図的に引き継ぐ必要があります。
サービスを L2TP/IPsec のままにする必要があるなら、サポートされる組み合わせは、事業者が実際に文書化しているクライアントと OS リリース、そして存在すればその自動化契約です。文書化された無人制御がない場合、正解はサポートされた手動接続であり、一つのビルドでたまたま動く脆い特権スクリプトではありません。
正しい自動化がすること
文書化された制御があれば、自動化の仕事は小さく防御可能です。名前付きの接続を要求し、準備完了を待ち、認証やセットアップの失敗で止まり、目的のワークロードを実行し、後片付けは接続を所有するコンポーネントに任せます。資格情報は、保存とローテーションを知っているクライアント側に残ります。
最初の一行を書く前に、どの層をどのコンポーネントが所有するかを書き出し、結果をそれに照らして確認してください。
- IPsec と PPP はクライアントが扱い、スクリプトのルートではありません。
- 接続はプラットフォームの VPN 状態に現れるので、アプリごとの範囲と always-on が適用されます。
- 内部サービス呼び出し、トランザクション番号、推測した引数が資格情報を運ぶことはありません。
- どの段階で失敗しても、半端に登録されたプロファイルは残りません。