Ayarlar'da VPN satırına dokunuyorsunuz, başkasının kurduğu bir profil görüyorsunuz ve onu ekleyen çağrıyı aramaya başlıyorsunuz. Böyle bir çağrı yok. Bir uygulama VpnService üzerinden kendi tünelini açabilir, ancak o listedeki girdiler platforma ve onları oluşturan istemciye aittir. Sınırın tam olarak nerede olduğunu bilmek, gizli sınıfların peşinde geçecek bir haftayı kurtarır.

Ayarlar ekranının gösterdiğiyle başlayın

VPN listesi, sistemin veya bir üretici istemcisinin kurduğu profillerin kaydıdır: PPTP, L2TP/IPsec, IKEv2 ve bir OEM uygulamasının ya da MDM'nin ittiği satırlar. Her satır bir sunucu adresi, kimlik bilgileri ve sürecinizin dışında yaşayan bir protokol uygulaması taşır. Kullanıcı orada Bağlan'a dokunduğunda tüneli platformun istemcisi kaldırır, sizin kodunuz değil. Bu yüzden satır yeniden başlatmadan sonra da kalır ve bu yüzden uygulamanızı kaldırmak onu hiçbir zaman silmez.

Kullanıcı tarafından liste bir API yüzeyi gibi görünür, VPN eklemenin bir niyet uzağında olması gereken bir yer. Öyle değil. Ona dokunan tek genel giriş noktaları gezinme niyetleridir ve içine yazan her şey platforma ya da ayrıcalıklı bir bileşene aittir.

Pratik sonuç: bir destek metni kullanıcılara profili Ayarlar'da eklemelerini söylüyorsa, uygulamanız o akışın hiçbir parçası değildir.

VpnService size gerçekte ne verir

VpnService ve VpnService.Builder, uygulamanızın sahip olduğu tek bir tüneli tanımlar. Adresler, rotalar, DNS sunucuları ve bir MTU eklersiniz, trafiği addAllowedApplication() veya addDisallowedApplication() ile sınırlarsınız ve ardından establish() bir TUN arayüzü için ParcelFileDescriptor döndürür. O andan itibaren uygulama IP paketlerini okur ve yanıtlar yazar, yani protokolü uygulamak veya gömmek sizin işinizdir: OpenVPN, WireGuard, özel bir taşıma.

Bu dizide hiçbir şey PPTP, L2TP/IPsec veya IKEv2 konuşmaz. Builder'da sistemin L2TP istemcisini kullan diyen bir anahtar yoktur ve platformun zaten sahip olduğu bir profili sürmenize izin veren bir geri çağırma da yoktur. Gerçek sınır budur ve bu bir izin boşluğu değil, tasarım sınırıdır.

Yani bir uygulama Android'de pekâlâ VPN istemcisi olabilir. Sadece telefonla gelen istemcilerin yöneticisi olamaz.

Onay iletişim kutusu süs değildir

Tüneliniz diğer uygulamaların trafiğini yakalayabildiği için, sistem kullanıcının bunu açıkça onaylamasını ister. prepare() başlatmanız gereken bir Intent döndürür, onay paketinize bağlıdır ve tünel açıkken durum çubuğu kalıcı bir gösterge gösterir. İkinci bir VPN açılırsa birincisi devre dışı kalır, çünkü Android aynı anda tek etkin VPN çalıştırır.

Bu tek-etkin kuralı testte insanları tökezletir. Kurumsal bir istemci bağlıyken kendi tünelinizi kaldırır ve kodunuzun bozuk olduğu sonucuna varırsınız, oysa platform yalnızca diğer istemciden geçmiştir. Onaylar sonradan geri alınabilir ve onay etkinliğinin bulunmadığı cihazlarda prepare() null döndürebilir, bu yüzden establish() yine de hatayı ele almalıdır.

Gizli API'ler ve ayar niyetleri

Eski yanıtlar yerleşik istemcinin kullandığı com.android.internal sınıflarına ve AIDL arayüzlerine işaret eder. Bunlar SDK'da yoktur, sürümler arasında haber verilmeden değişir ve uygulama mağazaları bu erişimi risk sayar. Cihazı rootlamak da onları kararlı kılmaz, çünkü root ve gizli API erişimi birbiriyle ilgisiz sorunlardır.

Desteklenen gezinme yardımı, değeri android.net.vpn.SETTINGS olan Settings.ACTION_VPN_SETTINGS'tir. Başlatmadan önce bunu çözümleyin, çünkü bazı OEM yapıları o etkinliği içermez ve çözümleme başarısız olursa yazılı adımlara dönün. Kullanıcıyı ekrana götürür ve hiçbir şey yapılandırmaz.

Cihaz sahibi ve MDM yolları, insanların genellikle kastettiği istisnadır. DevicePolicyManager her zaman açık bir VPN paketi belirleyebilir ve yönetilen yapılandırmalar bunları destekleyen bir istemci için ayarları önceden yükleyebilir, ama bu hâlâ PPTP profili yazan genel SDK değildir.

Kararı kullanıcı tarafından yürüyün

Ürününüz trafik taşımak zorundaysa VpnService ile gerçek bir protokol yığını planlayın ve onay akışı ile tek VPN kuralı için zaman ayırın. Amaç var olan bir kurumsal profile bağlanmaksa işiniz yönlendirmedir: ayarlar ekranına derin bağlantı, alanların belgelenmesi ve tüneli platform istemcisinin yapmasına izin vermek. Uygulamanın yalnızca özel bir uç noktaya ulaşması gerekiyorsa kendi tüneli hiç gerekmez.

Bu kararı kod yazmadan önce yazın, çünkü üç yol ilk sprintten sonra neredeyse hiç ortak noktaya sahip değildir.

Başlamadan önce son kontrol: gereksinim bizim uygulamamızın mı bağlandığını, yoksa cihazın mı bağlandığını söylüyor? Birincisi VpnService'tir, ikincisi oluşturamayacağınız bir profildir. O cümleyi doğru kurmak herhangi bir yeniden düzenlemeden daha ucuzdur.

İlgili makaleler