VPN

Android は、デベロッパーがバーチャル プライベート ネットワーク(VPN)を作成するための API を提供 説明します。このガイドを読むと、 独自の VPN クライアントを使用できます。

概要

VPN を使用すると、物理的にネットワークに接続されていないデバイスも VPN に安全にアクセスできます。 接続します

Android には、組み込みの(PPTP および L2TP/IPSec)VPN クライアントが含まれています。 レガシー VPN と呼ばれます。Android 4.0(API レベル 14)で導入された API により、 デベロッパーが独自の VPN ソリューションを提供できますVPN ソリューションをパッケージ化する アプリを実際にインストールして インストールしたりできますデベロッパーは通常 アプリが起動または停止されることがあります。

  • 組み込みのクライアントがサポートしていない VPN プロトコルを提供するため。
  • ユーザーが複雑な設定を行わずに VPN サービスに接続できるようにするため。

このガイドの残りの部分では、VPN アプリ( 常時オン VPN やアプリ単位の VPN など)であり、 構成する必要があります。

ユーザー エクスペリエンス

Android は、ユーザーがアプリの構成、起動、 停止できますシステム UI では、デバイスを使用するユーザーにも アクティブな VPN 接続を認識できます。Android では、以下の UI コンポーネントが表示されます。 VPN 接続:

  • VPN アプリを初めてアクティブにする前に、 接続リクエスト ダイアログが表示されます。ダイアログでは、デバイスを使用しているユーザーに、 VPN を信頼してリクエストを受け入れることを確認します。
  • VPN 設定画面([設定] > [ネットワークとインターネット] > [VPN])には、 ユーザーが接続リクエストを承認したアプリここにあるボタンでは VPN を削除することもできます。
  • 接続が完了すると、クイック設定トレイに情報パネルが表示されます アクティブです。ラベルをタップすると、詳細情報とリンクが記載されたダイアログが表示される [設定] に移動します。
  • ステータスバーには、アクティブな接続を示す VPN(鍵)アイコンがあります。

また、デバイスを使用するユーザーが次の操作を実行できる UI も備えている必要があります。 サービスのオプションを構成します。たとえば、ソリューションが次の条件を満たす必要があるとします。 アカウント認証の設定を取得します。アプリは次の UI を表示する必要があります。

  • 接続の開始と停止を手動で行うためのコントロール。常時接続 VPN 必要に応じて接続できますが、ユーザーが最初に接続を構成できるようにします。 継続的に確認できます
  • サービスがアクティブなときは非表示にできない通知。通知は、 接続ステータスを表示したり、ネットワーク統計情報などの詳細情報を表示したりできます。 通知をタップするとアプリがフォアグラウンドに表示されます。削除 通知を受け取ります。

VPN サービス

アプリは、ユーザー(または動作ネットワーク)のために プロファイル)を VPN ゲートウェイに接続します。各ユーザー(または仕事用プロファイル)は、 必要があります。システムが起動およびシャットダウンに使用する VPN サービスを VPN を停止し、接続ステータスを追跡できます。VPN サービスは VpnService

このサービスは、VPN ゲートウェイ接続用のコンテナとしても機能し、 管理することもできます。サービス インスタンスの呼び出し VpnService.Builder メソッド: 新しいローカル インターフェースを確立します。

<ph type="x-smartling-placeholder">
</ph>
図 1.VpnService が Android を接続する方法 ネットワーキングと接続して
VpnService がローカル TUN を作成する方法を示すブロック アーキテクチャの図
         インターフェースです。
をご覧ください。

アプリは次のデータを転送して、デバイスを VPN ゲートウェイに接続します。

  • ローカル インターフェースのファイル記述子から送信 IP パケットを読み取り、 VPN ゲートウェイに送信されます
  • 受信パケット(VPN ゲートウェイから受信して復号されたもの)を ファイル記述子を使用します。
で確認できます。

アクティブなサービスは、ユーザーまたはプロファイルごとに 1 つのみです。新しいサービスを開始すると、 既存のサービスを自動的に停止します。

サービスを追加する

アプリに VPN サービスを追加するには、 VpnService。アプリで VPN サービスを宣言する マニフェスト ファイルを次のように追加します。

  • BIND_VPN_SERVICE でサービスを保護する そのサービスにバインドできるのはシステムだけになります。
  • "android.net.VpnService" インテント フィルタを使用してサービスをアドバタイズし、 システムがサービスを見つけられるようにします

次の例は、アプリ マニフェスト ファイルでサービスを宣言する方法を示しています。

<service android:name=".MyVpnService"
         android:permission="android.permission.BIND_VPN_SERVICE">
     <intent-filter>
         <action android:name="android.net.VpnService"/>
     </intent-filter>
</service>

アプリでサービスを宣言すると、システムは自動的に 必要に応じてアプリの VPN サービスを停止できます。たとえば、システム コントロールは セキュリティを強化します。

サービスを準備する

アプリをユーザーの現在の VPN サービスにする準備をするには、 VpnService.prepare()。デバイスを使用するユーザーが アプリにすでに権限を付与している場合、メソッドはアクティビティ インテントを返します。 このインテントを使用して、権限を求めるシステム アクティビティを開始します。「 システムにより、他の権限ダイアログと同様のダイアログが カメラや連絡先へのアクセスを制御できます。アプリがすでに準備されている場合、メソッドは null

同時に準備できる VPN サービスは 1 つのみです。常に発信 VpnService.prepare(): ユーザーが異なる設定を行っている可能性があるため アプリが最後にこのメソッドを呼び出した後以降、アプリが VPN サービスとして識別されています。詳しくは以下をご覧ください。 「サービスのライフサイクル」セクションを参照してください。

サービスを接続する

サービスの稼働が完了したら、新しいローカル インターフェースを 1 台の VPN ゲートウェイに接続します権限をリクエストしてサービスに接続して 次の順序で手順を完了する必要があります。

  1. VpnService.prepare() を呼び出して権限をリクエストします( 必要)。
  2. VpnService.protect() を呼び出してアプリのトンネル ソケットを保持する システム VPN の外部に接続し、循環接続を回避します。
  3. DatagramSocket.connect() を呼び出してアプリのトンネルを接続します VPN ゲートウェイに接続します
  4. VpnService.Builder メソッドを呼び出して新しいローカル TUN インターフェース( ルーティングされます
  5. VpnService.Builder.establish() を呼び出して、 ローカル TUN インターフェースを確立し、ネットワーク経由で 行うことができます。

VPN ゲートウェイは通常、接続時にローカル TUN インターフェースの設定を提案します。 対応できます。アプリが VpnService.Builder メソッドを呼び出して、 サービス アカウント キーを取得します。

Kotlin

// Configure a new interface from our VpnService instance. This must be done
// from inside a VpnService.
val builder = Builder()

// Create a local TUN interface using predetermined addresses. In your app,
// you typically use values returned from the VPN gateway during handshaking.
val localTunnel = builder
        .addAddress("192.168.2.2", 24)
        .addRoute("0.0.0.0", 0)
        .addDnsServer("192.168.1.1")
        .establish()

Java

// Configure a new interface from our VpnService instance. This must be done
// from inside a VpnService.
VpnService.Builder builder = new VpnService.Builder();

// Create a local TUN interface using predetermined addresses. In your app,
// you typically use values returned from the VPN gateway during handshaking.
ParcelFileDescriptor localTunnel = builder
    .addAddress("192.168.2.2", 24)
    .addRoute("0.0.0.0", 0)
    .addDnsServer("192.168.1.1")
    .establish();

アプリごとの VPN セクションの例は、以下を含む IPv6 構成を示しています。 その他のオプションです次の VpnService.Builder 値を追加する必要があります。 新しいインターフェースを確立する前に、以下の点を確認してください。

addAddress()
IPv4 アドレスまたは IPv6 アドレスを少なくとも 1 つと、システムで設定するサブネット マスクを追加する をローカル TUN インターフェース アドレスとして割り当てます。通常、アプリは IP アドレスを ハンドシェイク中に VPN ゲートウェイからアドレスとサブネット マスクを取得します。
addRoute()
システムが VPN 経由でトラフィックを送信するようにする場合は、ルートを 1 つ以上追加します。 行うことができます。ルートは宛先アドレスでフィルタします。すべてのトラフィックを受け入れるには、 0.0.0.0/0::/0 などのオープンルート。

establish() メソッドは アプリが読み取りと書き込みに使用する ParcelFileDescriptor インスタンス インターフェースのバッファとの間のパケットを送受信します。establish() アプリの準備ができていない場合、または誰かがアプリを取り消した場合、メソッドは null を返します。 付与します。

サービスのライフサイクル

アプリは、システムで選択した VPN のステータスと、有効な VPN を 接続しますアプリのユーザー インターフェース(UI)を更新して、 デバイスが変更を認識することです。

サービスの開始

VPN サービスは次の方法で開始できます。

  • アプリは通常、ユーザーが接続ボタンをタップするとサービスを開始します。
  • システムは、常時接続 VPN がオンになっているとサービスを開始します。

アプリは、次のようにインテントを渡して VPN サービスを開始します。 startService()。詳しくは、 サービス

システムがバックグラウンドでサービスを開始するため、 onStartCommand()。ただし Android では、 バージョン 8.0(API レベル 26)以降のバックグラウンド アプリこれらをサポートしている場合 API レベルでは、API レベルを呼び出すことで、サービスをフォアグラウンドに移行する必要があります。 Service.startForeground()。詳細については、 起動します

サービスの停止

デバイスを使用しているユーザーは、アプリの UI を使用してサービスを停止できます。停止 サービスを使用します。システムはアクティブな デバイスを使用しているユーザーが VPN 画面で次の操作を行ったとき。 [設定] アプリ:

  • VPN アプリを切断または削除する
  • アクティブな接続の常時接続 VPN をオフにする

システムはサービスの onRevoke() メソッドを呼び出しますが、この呼び出しは メインスレッドでは実行されない場合があります。このメソッドが呼び出されると、 代替ネットワークインターフェースが トラフィックをルーティングしています安全に廃棄できます 次のリソースをご覧ください。

  • 次を呼び出して、VPN ゲートウェイへの保護されたトンネル ソケットを閉じます。 DatagramSocket.close()
  • 次の呼び出しを使用して、Parcel ファイル ディスクリプタを閉じます(ドレインする必要はありません)。 ParcelFileDescriptor.close()

常時接続 VPN

Android はデバイスの起動時に VPN サービスを開始し、VPN サービスを使用し続けます。 確認できます。この機能は常時接続 VPN と呼ばれ、 Android 7.0(API レベル 24)以降。Android がサービスを維持している間、 その VPN ゲートウェイの役割を果たすのは VPN サービス 接続します常時接続 VPN は、VPN を使用しない接続もブロックできます。

ユーザー エクスペリエンス

Android 8.0 以降では、次のダイアログが表示されます。 常時接続 VPN を認識しているデバイスを使用している人:

  • 常時接続 VPN 接続が切断された場合や接続できない場合、 閉じることができない通知を表示します。通知をタップすると、ダイアログが表示され、 をご覧ください。VPN に再接続するか誰かが接続すると、通知は表示されなくなります 常時接続 VPN オプションをオフにします。
  • 常時接続 VPN では、デバイスを使用しているユーザーはあらゆるネットワークをブロックできます。 内部 IP アドレスを使用して通信できますこのオプションをオンにすると、 VPN を利用する前にインターネット接続がないことをユーザーに警告する 接続します設定アプリから、デバイスを使用しているユーザーに続行するか、 キャンセルします。

ユーザーではなくシステムが常時接続を開始および停止するため、 アプリの動作とユーザー インターフェースを適応させる必要があります。

  1. システムや設定が原因で接続を切断する UI を無効にします。 アプリが接続を制御します。
  2. アプリを起動するたびに構成を保存し、接続を構成する できます。システムはオンデマンドでアプリを起動するため、ユーザーは デバイスを使用するユーザーは、接続を構成する必要がない場合もあります。

管理対象設定を使用して、 接続します管理対象設定は、IT 管理者がリモートで VPN を設定するのに役立ちます。

常時接続を検出する

Android には、システムが VPN を開始したかどうかを確認する API はありません。 あります。しかし、アプリが起動したサービス インスタンスにフラグを立てると、 常時接続 VPN のフラグなしサービスがシステムによって開始されたことを意味します。次に例を示します。

  1. Intent インスタンスを作成して VPN サービスを開始します。
  2. インテントに拡張データを追加することで、VPN サービスにフラグを立てます。
  3. サービスの onStartCommand() メソッドで、 フラグを指定します。intent

ブロックされた接続

デバイスを使用するユーザー(または IT 管理者)は、すべてのトラフィックに VPN の使用を強制できます。 VPN を使用しないネットワーク トラフィックはすべてシステムがブロックします。 デバイスの VPN オプションに [VPN 以外の接続をブロック] スイッチがある [設定] の [設定] で

常時接続を無効にする

アプリが現在、常時接続 VPN に対応できない場合は、無効にすることができます(Android 8.1 以上)を使用するには、 SERVICE_META_DATA_SUPPORTS_ALWAYS_ON サービス メタデータを false に追加する。次のアプリ マニフェストの例は、 metadata 要素:

<service android:name=".MyVpnService"
         android:permission="android.permission.BIND_VPN_SERVICE">
     <intent-filter>
         <action android:name="android.net.VpnService"/>
     </intent-filter>
     <meta-data android:name="android.net.VpnService.SUPPORTS_ALWAYS_ON"
             android:value=false/>
</service>

アプリで常時接続 VPN をオプトアウトすると、オプション UI が無効になります コントロールできます。

アプリ別の VPN

VPN アプリは、ネットワーク経由でトラフィックを送信できるインストール済みのアプリを除外できます。 接続します許可リストまたは禁止リストを作成して 両方はできません許可リストまたは拒否リストを作成しなかった場合は、 トラフィックをブロックします。

VPN アプリは、接続を確立する前にリストを設定する必要があります。もし リストを変更し、新しい VPN 接続を確立する必要があります。アプリは以下の要件を満たす必要があります。 リストに追加したときに、デバイスにインストールされたままになります。

Kotlin

// The apps that will have access to the VPN.
val appPackages = arrayOf(
        "com.android.chrome",
        "com.google.android.youtube",
        "com.example.a.missing.app")

// Loop through the app packages in the array and confirm that the app is
// installed before adding the app to the allowed list.
val builder = Builder()
for (appPackage in appPackages) {
    try {
        packageManager.getPackageInfo(appPackage, 0)
        builder.addAllowedApplication(appPackage)
    } catch (e: PackageManager.NameNotFoundException) {
        // The app isn't installed.
    }
}

// Complete the VPN interface config.
val localTunnel = builder
        .addAddress("2001:db8::1", 64)
        .addRoute("::", 0)
        .establish()

Java

// The apps that will have access to the VPN.
String[] appPackages = {
    "com.android.chrome",
    "com.google.android.youtube",
    "com.example.a.missing.app"};

// Loop through the app packages in the array and confirm that the app is
// installed before adding the app to the allowed list.
VpnService.Builder builder = new VpnService.Builder();
PackageManager packageManager = getPackageManager();
for (String appPackage: appPackages) {
  try {
    packageManager.getPackageInfo(appPackage, 0);
    builder.addAllowedApplication(appPackage);
  } catch (PackageManager.NameNotFoundException e) {
    // The app isn't installed.
  }
}

// Complete the VPN interface config.
ParcelFileDescriptor localTunnel = builder
    .addAddress("2001:db8::1", 64)
    .addRoute("::", 0)
    .establish();

許可されているアプリ

許可リストにアプリを追加するには、 VpnService.Builder.addAllowedApplication()。条件 リストに 1 つ以上のアプリが含まれている場合、リスト内のアプリのみが VPN を使用します。 他のすべてのアプリ(リストに含まれないアプリ)は、VPN 接続であるかのようにシステム ネットワークを使用します。 停止します。許可リストが空の場合、すべてのアプリが VPN を使用します。

禁止されているアプリ

アプリを禁止リストに追加するには、呼び出します。 VpnService.Builder.addDisallowedApplication()。 許可されていないアプリは、VPN が実行されていないかのようにシステム ネットワークを使用します。 アプリが VPN を使用します。

VPN をバイパスする

VPN を使用すると、アプリは VPN をバイパスして独自のネットワークを選択できます。宛先 VPN をバイパスする場合は、次の場合に VpnService.Builder.allowBypass() を呼び出します。 確立しますこの値は、 接続します。アプリがプロセスまたはソケットを特定のサービス アカウントにバインドしない場合、 アプリのネットワーク トラフィックは、引き続き VPN を経由します。

特定のネットワークにバインドするアプリの場合、ユーザーが VPN を経由しないトラフィックをブロックします。トラフィックを特定のネットワーク経由で ファイアウォール ルールなど、 ConnectivityManager.bindProcessToNetwork() または Network.bindSocket() の後にソケットを接続します。

サンプルコード

Android オープンソース プロジェクトには、ToyVPN というサンプルアプリが含まれています。 このアプリは VPN サービスの設定方法と接続方法を示します。