VPN

Android menyediakan API bagi developer untuk membuat virtual private network (VPN) terkemuka. Setelah membaca panduan ini, Anda akan mengetahui cara mengembangkan dan menguji klien VPN untuk perangkat Android.

Ringkasan

VPN memungkinkan perangkat yang secara fisik tidak berada di jaringan untuk mengakses jaringan.

Android menyertakan klien VPN bawaan (PPTP dan L2TP/IPSec), yang terkadang yang disebut VPN lama. Android 4.0 (API Level 14) memperkenalkan API sehingga aplikasi developer dapat menyediakan solusi VPN mereka sendiri. Anda mengemas solusi VPN menjadi aplikasi yang diinstal orang ke perangkat. Developer biasanya membuat VPN karena salah satu alasan berikut:

  • Untuk menawarkan protokol VPN yang tidak didukung oleh klien bawaan.
  • Untuk membantu orang terhubung ke layanan VPN tanpa konfigurasi yang rumit.

Bagian selanjutnya dari panduan ini akan menjelaskan cara mengembangkan aplikasi VPN (termasuk VPN selalu aktif dan per aplikasi) serta tidak mencakup klien VPN bawaan.

Pengalaman pengguna

Android menyediakan antarmuka pengguna (UI) untuk membantu seseorang mengonfigurasi, memulai, dan menghentikan solusi VPN. UI sistem juga membuat orang yang menggunakan perangkat mengetahui adanya koneksi VPN aktif. Android menampilkan komponen UI berikut untuk Koneksi VPN:

  • Sebelum aplikasi VPN dapat aktif untuk pertama kalinya, sistem akan menampilkan dialog permintaan koneksi. Dialog meminta pengguna perangkat untuk mengkonfirmasi bahwa mereka memercayai VPN dan menerima permintaan tersebut.
  • Layar setelan VPN (Setelan > Jaringan & Internet > VPN) menampilkan VPN aplikasi di mana pengguna menerima permintaan koneksi. Ada tombol untuk mengonfigurasi opsi sistem atau melupakan VPN.
  • Baki Setelan Cepat menampilkan panel informasi saat sambungan aktif. Mengetuk label akan menampilkan dialog berisi informasi lebih lanjut dan link ke Setelan.
  • Status bar berisi ikon (kunci) VPN, menunjukkan bahwa koneksi sedang aktif.

Aplikasi Anda juga harus menyediakan UI sehingga pengguna perangkat dapat mengonfigurasi opsi layanan Anda. Misalnya, solusi Anda mungkin perlu menangkap pengaturan otentikasi akun. Aplikasi akan menampilkan UI berikut:

  • Kontrol untuk memulai dan menghentikan koneksi secara manual. VPN yang Selalu aktif dapat terhubung saat diperlukan, tetapi izinkan orang untuk mengkonfigurasi koneksi terlebih dahulu berapa kali mereka menggunakan VPN Anda.
  • Notifikasi yang tidak dapat ditutup saat layanan aktif. Notifikasi tersebut dapat menampilkan status koneksi atau memberikan informasi selengkapnya—seperti statistik jaringan. Mengetuk notifikasi akan membawa aplikasi ke latar depan. Hapus notifikasi setelah layanan menjadi tidak aktif.

Layanan VPN

Aplikasi Anda menghubungkan jaringan sistem untuk pengguna (atau kantor ) ke gateway VPN. Setiap pengguna (atau profil kerja) dapat menjalankan aplikasi VPN yang berbeda. Anda membuat layanan VPN yang digunakan sistem untuk memulai dan menghentikan VPN, dan melacak status koneksi. Layanan VPN Anda mewarisi dari VpnService

Layanan ini juga berfungsi sebagai kontainer Anda untuk koneksi {i>gateway VPN<i} dan antarmuka perangkat lokal mereka. Panggilan instance layanan Anda Metode VpnService.Builder untuk membuat antarmuka lokal baru.

Gambar 1. Cara VpnService menghubungkan Android jaringan ke gateway VPN
Diagram blok arsitektur yang menunjukkan cara VpnService membuat TUN lokal
         dalam jaringan sistem.

Aplikasi Anda mentransfer data berikut untuk menghubungkan perangkat ke gateway VPN:

  • Membaca paket IP keluar dari deskriptor file antarmuka lokal, mengenkripsi dan mengirimkannya ke gateway VPN.
  • Menulis paket masuk (diterima dan didekripsi dari gateway VPN) ke deskriptor file antarmuka lokal.

Hanya ada satu layanan aktif per pengguna atau profil. Memulai layanan baru, secara otomatis menghentikan layanan yang ada.

Menambahkan layanan

Untuk menambahkan layanan VPN ke aplikasi, buat layanan Android yang mewarisi VpnService Mendeklarasikan layanan VPN di aplikasi Anda file manifes dengan tambahan berikut:

  • Melindungi layanan dengan BIND_VPN_SERVICE sehingga hanya sistem yang dapat mengikat ke layanan Anda.
  • Iklankan layanan dengan filter intent "android.net.VpnService" sehingga sistem dapat menemukan layanan Anda.

Contoh ini menunjukkan cara mendeklarasikan layanan di file manifes aplikasi Anda:

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

Setelah aplikasi Anda mendeklarasikan layanan, sistem dapat secara otomatis memulai dan menghentikan layanan VPN aplikasi Anda saat diperlukan. Misalnya, sistem mengontrol layanan Anda saat menjalankan VPN selalu aktif.

Menyiapkan layanan

Untuk menyiapkan aplikasi menjadi layanan VPN pengguna saat ini, panggil VpnService.prepare() Jika pengguna perangkat belum sudah memberikan izin untuk aplikasi Anda, metode akan mengembalikan intent aktivitas. Gunakan intent ini untuk memulai aktivitas sistem yang meminta izin. Tujuan menampilkan dialog yang mirip dengan dialog izin lainnya, seperti akses kamera atau kontak. Jika aplikasi Anda sudah siap, metode akan menampilkan null.

Hanya satu aplikasi yang dapat menjadi layanan VPN yang disiapkan saat ini. Selalu panggil VpnService.prepare() karena seseorang mungkin telah menetapkan sebagai layanan VPN karena aplikasi Anda terakhir kali memanggil metode tersebut. Untuk mempelajari lebih lanjut, lihat di bagian Siklus proses layanan.

Menghubungkan layanan

Setelah layanan berjalan, Anda bisa membuat antarmuka lokal baru yang terhubung ke gateway VPN. Untuk meminta izin dan terhubung ke layanan Anda untuk gateway VPN, Anda harus menyelesaikan langkah-langkah dalam urutan berikut:

  1. Panggil VpnService.prepare() untuk meminta izin (saat diperlukan).
  2. Panggil VpnService.protect() untuk mempertahankan soket tunnel aplikasi Anda di luar VPN sistem dan menghindari koneksi sirkular.
  3. Panggil DatagramSocket.connect() untuk menghubungkan tunnel aplikasi Anda menghubungkan ke gateway VPN.
  4. Panggil metode VpnService.Builder untuk mengonfigurasi lokal baru antarmuka TUN di untuk lalu lintas VPN.
  5. Panggil VpnService.Builder.establish() agar sistem menetapkan antarmuka TUN lokal dan mulai mengarahkan traffic melalui dalam antarmuka berbasis web yang sederhana.

Gateway VPN biasanya menyarankan setelan untuk antarmuka TUN lokal selama berjabat tangan. Aplikasi Anda memanggil metode VpnService.Builder untuk mengonfigurasi seperti yang ditunjukkan dalam contoh berikut:

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();

Contoh di bagian VPN Per-aplikasi menunjukkan konfigurasi IPv6 yang mencakup opsi lainnya. Anda perlu menambahkan nilai VpnService.Builder berikut sebelum Anda dapat membuat antarmuka baru:

addAddress()
Tambahkan setidaknya satu alamat IPv4 atau IPv6 beserta subnet mask yang digunakan sistem ditetapkan sebagai alamat antarmuka TUN lokal. Aplikasi Anda biasanya menerima IP dan subnet mask dari gateway VPN selama handshake.
addRoute()
Tambahkan setidaknya satu rute jika Anda ingin sistem mengirim traffic melalui VPN dalam antarmuka berbasis web yang sederhana. Merutekan filter berdasarkan alamat tujuan. Untuk menerima semua traffic, setel membuka rute seperti 0.0.0.0/0 atau ::/0.

Metode establish() menampilkan Instance ParcelFileDescriptor yang digunakan aplikasi Anda untuk membaca dan menulis paket ke dan dari {i>buffer<i} antarmuka. establish() menampilkan null jika aplikasi Anda tidak siap atau seseorang mencabut izin akses.

Siklus proses layanan

Aplikasi Anda harus melacak status VPN yang dipilih sistem dan aktivitas koneksi jarak jauh. Update antarmuka pengguna (UI) aplikasi Anda agar pengguna tetap menggunakan perangkat mengetahui setiap perubahan.

Memulai layanan

Layanan VPN Anda dapat dimulai dengan cara berikut:

  • Aplikasi Anda memulai layanan—biasanya karena pengguna mengetuk tombol sambungkan.
  • Sistem memulai layanan karena VPN selalu aktif diaktifkan.

Aplikasi Anda memulai layanan VPN dengan meneruskan intent ke startService() Untuk mempelajari lebih lanjut, baca Memulai layanan.

Sistem memulai layanan Anda di latar belakang dengan memanggil onStartCommand() Akan tetapi, Android menerapkan pembatasan aplikasi latar belakang dalam versi 8.0 (API Level 26) atau yang lebih tinggi. Jika Anda mendukung API Level, Anda perlu mentransisikan layanan Anda ke latar depan dengan memanggil Service.startForeground() Untuk mempelajari lebih lanjut, baca Menjalankan layanan di latar depan.

Menghentikan layanan

Pengguna perangkat dapat menghentikan layanan Anda dengan menggunakan UI aplikasi Anda. Hentikan layanan alih-alih hanya menutup koneksi. Sistem juga menghentikan koneksi saat pengguna perangkat melakukan hal berikut di layar VPN aplikasi Setelan:

  • memutus atau melupakan aplikasi VPN
  • menonaktifkan VPN selalu aktif untuk koneksi yang aktif

Sistem memanggil metode onRevoke() layanan Anda, tetapi panggilan ini mungkin tidak terjadi di thread utama. Bila sistem memanggil metode ini, antarmuka jaringan alternatif sudah mengarahkan lalu lintas data. Anda dapat membuang dengan aman referensi berikut:

VPN selalu aktif

Android dapat memulai layanan VPN saat perangkat melakukan booting dan menjaganya tetap berjalan saat apakah perangkat menyala. Fitur ini disebut VPN selalu aktif dan tersedia di Android 7.0 (API Level 24) atau yang lebih tinggi. Meskipun Android mengelola layanan adalah layanan VPN Anda yang bertanggung jawab atas gateway VPN koneksi jarak jauh. VPN selalu aktif juga dapat memblokir koneksi yang tidak menggunakan VPN.

Pengalaman pengguna

Di Android 8.0 atau yang lebih tinggi, sistem menampilkan dialog berikut untuk membuat orang yang menggunakan perangkat mengetahui VPN yang selalu aktif:

  • Jika koneksi VPN yang selalu aktif terputus atau tidak dapat terhubung, orang akan melihat notifikasi yang tidak dapat ditutup. Mengetuk notifikasi akan menampilkan dialog yang menjelaskan lebih lanjut. Notifikasi menghilang saat VPN terhubung kembali atau seseorang menonaktifkan opsi VPN yang selalu aktif.
  • VPN selalu aktif memungkinkan pengguna perangkat memblokir jaringan apa pun koneksi yang tidak menggunakan VPN. Jika mengaktifkan opsi ini, aplikasi memperingatkan orang bahwa mereka tidak memiliki koneksi internet sebelum VPN menghubungkan Anda. Aplikasi Setelan meminta pengguna yang menggunakan perangkat untuk melanjutkan atau batalkan.

Karena sistem (dan bukan seseorang) memulai dan menghentikan koneksi yang selalu aktif, Anda perlu menyesuaikan perilaku aplikasi dan antarmuka pengguna:

  1. Nonaktifkan UI apa pun yang memutuskan koneksi karena sistem dan Setelan aplikasi mengontrol koneksi.
  2. Simpan konfigurasi apa pun antara setiap aplikasi yang dimulai dan konfigurasikan koneksi dengan setelan terbaru. Karena sistem memulai aplikasi sesuai permintaan, orang menggunakan perangkat itu mungkin tidak selalu ingin mengkonfigurasi koneksi.

Anda juga dapat menggunakan konfigurasi terkelola untuk mengonfigurasi koneksi jarak jauh. Konfigurasi terkelola membantu admin IT mengonfigurasi VPN dari jarak jauh.

Mendeteksi selalu aktif

Android tidak menyertakan API untuk mengonfirmasi apakah sistem telah memulai VPN Anda layanan. Namun, saat aplikasi menandai instance layanan apa pun yang dimulai, Anda dapat mengasumsikan bahwa sistem memulai layanan yang tidak ditandai untuk VPN selalu aktif. Berikut contohnya:

  1. Buat instance Intent untuk memulai layanan VPN.
  2. Tandai layanan VPN dengan menempatkan tambahan ke intent.
  3. Dalam metode onStartCommand() layanan, cari metode dalam tambahan argumen intent.

Koneksi diblokir

Pengguna perangkat (atau admin IT) dapat memaksa semua traffic untuk menggunakan VPN. Sistem memblokir semua traffic jaringan yang tidak menggunakan VPN. Orang-orang yang menggunakan perangkat dapat menemukan tombol Blokir koneksi tanpa VPN di opsi VPN panel di Setelan.

Menghentikan penggunaan selalu aktif

Jika saat ini aplikasi Anda tidak dapat mendukung VPN yang selalu aktif, Anda dapat memilih tidak ikut (di Android 8.1 atau yang lebih baru) dengan menyetel atribut SERVICE_META_DATA_SUPPORTS_ALWAYS_ON metadata layanan ke false. Contoh manifes aplikasi berikut menunjukkan cara menambahkan elemen 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>

Ketika aplikasi Anda memilih untuk tidak menggunakan VPN yang selalu aktif, sistem akan menonaktifkan UI opsi kontrol di Setelan.

VPN per aplikasi

Aplikasi VPN dapat memfilter aplikasi terinstal mana yang diizinkan untuk mengirimkan traffic melalui koneksi VPN. Anda dapat membuat daftar yang diizinkan atau daftar yang tidak diizinkan, tetapi tidak keduanya. Jika Anda tidak membuat daftar yang diizinkan atau yang tidak diizinkan, sistem akan mengirimkan semua lalu lintas jaringan melalui VPN.

Aplikasi VPN Anda harus menetapkan daftar sebelum koneksi dibuat. Jika Anda mengubah daftar, membuat koneksi VPN baru. Aplikasi harus diinstal pada perangkat ketika Anda menambahkannya ke daftar.

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();

Aplikasi yang diizinkan

Untuk menambahkan aplikasi ke daftar yang diizinkan, panggil VpnService.Builder.addAllowedApplication() Jika daftar mencakup satu atau beberapa aplikasi, lalu hanya aplikasi dalam daftar yang menggunakan VPN. Semua aplikasi lain (yang tidak ada dalam daftar) menggunakan jaringan sistem seolah-olah VPN tidak berjalan. Jika daftar yang diizinkan kosong, semua aplikasi dapat menggunakan VPN.

Aplikasi yang tidak diizinkan

Untuk menambahkan aplikasi ke daftar yang tidak diizinkan, panggil VpnService.Builder.addDisallowedApplication() Aplikasi yang tidak diizinkan menggunakan jaringan sistem seolah-olah VPN tidak berjalan—semua aplikasi apa pun menggunakan VPN.

Mem-bypass VPN

VPN dapat mengizinkan aplikasi untuk mem-bypass VPN dan memilih jaringannya sendiri. Kepada tidak menggunakan VPN, panggil VpnService.Builder.allowBypass() saat pembuatan antarmuka VPN. Anda tidak dapat mengubah nilai ini setelah memulai layanan VPN. Jika aplikasi tidak mengikat proses mereka atau soket ke jaringan, traffic jaringan aplikasi akan berlanjut melalui VPN.

Aplikasi yang terikat ke jaringan tertentu tidak memiliki koneksi saat seseorang memblokir lalu lintas data yang tidak melewati VPN. Untuk mengirim traffic melalui jaringan, metode panggilan aplikasi, seperti ConnectivityManager.bindProcessToNetwork() atau Network.bindSocket() sebelum menghubungkan soket.

Kode contoh

Proyek Open Source Android mencakup aplikasi contoh yang disebut ToyVPN. Aplikasi ini menunjukkan cara menyiapkan dan menghubungkan layanan VPN.