[Android開発の考え方] 自分のVPNアプリを作成する:Android VpnManager開発の考え方と心得

前書き

この投稿では、
自分で研究したAndroid VPNアプリの開発の考え方を共有します。
初心者でも経験豊富な開発者でも、
これらのノートは実用的なガイドを提供します。
皆さんの役に立てば幸いです。

事前に考慮すべき問題
どのように実装するかを考えるため、まずはネイティブにどのようなVPN暗号化接続方式があるかを調査しました
  • ここでは、ネイティブのAndroid AOSPソースコード内にあるVPN接続暗号化方式を見ました:
    • PPTP
    • L2TP/IPSec PSK
    • IPSec Xauth Psk
    • IPSec IKEv2 PSK
    • L2TP/IPSec RSA
    • IPSec Xauth RSA
    • IPSec 混合 RSA
    • IPSec IKEv2 RSA
もしVPN接続暗号化モード機能を実装する必要がある場合:
  • 公式のネイティブ提供方法には:VpnManager、 VpnService 調査の結果:
    • VpnManagerを使用する場合、一部のVpn接続モードのみが提供されており、高バージョン(API 30以上)でのみ利用可能
    • VpnServiceを使用する場合、基本的な設定のみが提供されており、上層で使用するための接続モードのインターフェースは開放されていない
  • VpnManagerはAPI 30以上で使用可能で、一部のプロトコルのみが開放されている
    • また、Googleのissue trackerサイトで、
      他の開発者が類似の問題を抱えており、公式に下層の接続モードを上層で使用できるように開放してほしいと質問しているのを見ました。
      公式の回答では、将来的に開放される可能性があるとのこと:こちらをクリック
      つまり、他にも同様のニーズがあるが、現時点では公式の開発予定はない
  • 以前述べたように、公式は一部の暗号化方式のみをサポートしており、その他は自分で実装するか、サードパーティのライブラリを統合する必要があります。
    この図は、公式がサポートする3つの暗号化方式を示しています:IPSec IKEv2 PSK、IPSec IKEv2 RSA、IPSec User Pass。
    vpn_limit.png
VPN実装の考え方の参考
  • 公式提供の方法を使用する場合、以下のように実装できます:
    • '接続タイプ'VpnManager (APIレベル30以上)のprovisionVpnProfileメソッドを使用してPlatformVpnProfileを設定
      • 公式は新しいクラスPlatformVpnProfileを定義しています
        • AOSPと組み合わせて見ると、公式はこのクラスを提供して一部の接続プロトコルを設定できるようにしています 最終的に下層のサービスに到達すると、サービスで使用されるVpnProfileクラスに変換されます
        • つまり、VpnManagerのline 335provisionVpnProfile(@NonNull PlatformVpnProfile profile) 最終的にはtoVpnProfile()を使用してPlatformVpnProfileVpnProfileに変換します
  • そのIkev2VpnProfile.BuilderはIkev2関連の接続設定を行うことができ、このクラスは実際にはPlatformVpnProfileを実装して、オープンなプロトコルモードを設定するためのものです。

  • 'VPN設定関連' : VpnServiceを通じて、ローカルトンネルを作成する際にVpnService.Builder()を追加します。
    • 公式の VpnServiceアーキテクチャ図
      • この方法は接続時のトンネルを設定し、公式には以下の例に示す方法のみが提供されています。
      • AOSPには関連するプロトコル接続が提供されていますが、まだ公開されていません。 したがって、関連するプロトコルで接続する必要がある場合は、自分で開発する必要があります。
      • 例 :
        /***  Android level 14 up ***/
        val builder = VpnService.Builder()
        val localTunnel = builder
                         .setSession('VPN名前')  
                         .addAddress('サ', 'prefix length')
                         .addRoute('転送ルト', 'prefix length')
                         .addDnsServer('DNS')
                         .addSearchDomain('DNS検索ドメイン')
                         .establish()
        


他の方法やサードパーティのソリューションを使用してVPNアプリを実装する
公式に提供されている方法では要件を満たせない場合、以下を検討できます:
  • AnyConnect:サードパーティのVPNプロバイダーで、現在サードパーティのVPNサービスが見られます。
    • AnyConnect公式ドキュメントには、TLS、DTLS、IPsec IKEv2などのプロトコルが提供されていると記載されています。
    • 別のAnyConnectドキュメントには、IPsec IKEv2接続を使用するにはCisco Adaptive Security Appliance 8.4以上が必要と記載されています。
    • このオプションを使用する場合、ベンダーと連絡を取る必要があり、開発方法や詳細を知ることができます。
    • この表の下部には、各プラットフォームがサポートするトンネリングについて説明する表があります。
    • AnyConnect 4.10リリースノートには、Androidバージョンに関する一部の互換性問題についても記載されています:
      • 例えば、Android 5.0、6.0の省電力モードはこのサービスと競合します。
      • Split DNSはAndroid 4.4またはSamsung 5.x Androidデバイスでは動作しません。
  • (参考) ネット上で見つけた方法で、反射フレームワーク内のメソッドを直接使用してVpnProfileを設定する:Create VPN profile on Android
    • しかし、Android 9.0以上ではこの方法は修正されているため、古いデバイスではこの方法が使用されている可能性があります(対象デバイスがこれ以前の場合、検討できます)。
    • 修正アナウンス
  • (参考) サードパーティのopenVpnはAndroidのオープンソースを提供しています。
    • ドキュメントには、SSL/TLSプロトコルをサポートしていると記載されています(このプロトコルのみサポート)。
    • openVpnをAndroidプロジェクトに追加する方法:こちら
    • ics-openvpn FAQには、Samsung 5.0デバイスの問題についても記載されています。


その他の知識ポイント
  • アプリを通じてカスタムVpnServiceを起動する際、Android 8.0以上ではサービスの動作にバックグラウンド実行制限が追加されました。

  • android-10.0.0_r1 aosp内の VpnService.javaline:176~179では IConnectivityManager.aidlが使用されていますが、現在のところframework層でaidlの実装の痕跡は見つかっていません。 そのため、binderなどに置かれている可能性があり、実装方法を理解するにはさらに低レベルのコードを調査する必要があります。

  • Android 12 aosp内の VpnService.Javaline:178~181ではaidlがIVpnManager.aidlに変更されています。 ソースコード内にはもう一つのファイルとしてVpnManagerService.Javaがあります。

    そのline:293provisionVpnProfile(VpnProfile profile,...) このメソッドは変数VpnProfileを提供することを要求します。

    VpnProfileのline:97を確認すると、そのデフォルト接続方式は:public int type = TYPE_PPTPです。

    また、VpnProfileで設定可能な接続モードは以下の通りです:
    vpn_aosp_type.png
    ただし、これらは現在aosp内でのみサポートされています。
    公開されていないため、アプリ内で直接使用することはできません。
    まとめると、
    一般ユーザーは携帯電話の設定から変更するしかありません。
    開発者はaospから手をつけるしかありません。

You might also enjoy