Bir VpnService uygulamasında bölünmüş tünelleme birkaç belirli yerde kırılır ve onarım her biri için farklıdır. İstemci yalnızca başarısız olan tek bir hedef gösterir, bu yüzden ilk iş hangi sınıra çarptığınızı bulmaktır: builder'ın aldığı rotalar, kimlik doğrulayamadığınız proxy, yalnızca duyurduğunuz resolver veya platformun kullanıcı başına uyguladığı uygulama listesi. Tam bu yüzden dört adımlı bir kontrol tutuyorum. Aşağıdaki sırayla ilerler ve ilk hatada durur.

Builder'ın platforma ne verdiğini doğrulayın

VpnService.Builder bir bildirim listesidir. establish() sanal arayüz için bir ParcelFileDescriptor döndürür ve platform bu tanımlayıcıya yalnızca addAddress ile addRoute öneklerine uyan trafiği gönderir; addDnsServer istemcilere hangi resolver'ı soracaklarını söyler. Eklediğiniz tüm öneklerin dışındaki bir hedef, arayüz ne vaat ederse etsin uygulamanıza asla ulaşmaz. Bu tek gerçek, kodu değiştirmeden önceki bozuk bölünmüş tünelleme bildirimlerinin çoğunu açıklar.

Builder'ınızın derlediği adres, rota ve DNS listelerini günlüğe yazın, sonra bunları başarısız olan hedeflerle karşılaştırın. Yönetim ana bilgisayarı için eksik bir /32, bozuk bir tünelden çok daha yaygındır. Liste doğruysa devam edin; yanlışsa kontrol listesinin geri kalanı boşa emektir.

excludeRoute yalnızca API 33'ten itibaren var

Hedefe dayalı dışlama, en sık destek konusuna dönüşen istektir. builder.excludeRoute(IpPrefix) API 33 ile geldi; öncesinde desteklenen tek yaklaşım dışlanan önek dışındaki her şeye rota eklemektir, yani tamamlayıcı önekleri kendiniz hesaplamanız gerekir. İki çağrı birbirinin aynası değildir: biri arayüzün rota kümesinden çıkarır, diğeri kümeyi sıfırdan kurar ve eski bir cihaz tanımadığı çağrıyı fırlatır ya da sessizce yok sayar. Build.VERSION.SDK_INT'e göre dallanın ve iki yolu da gerçek donanımda test edin.

Tamamlayıcıları hesaplarken önek hizasına dikkat edin. /16 rota içindeki /24 dışlaması, kalanı gerçekten tanımlayan kapsayıcı önekleri gerektirir, tek bir bozuk /8 değil. Son listeyi günlüğe yazın ve dışlanan ana bilgisayarın hâlâ tünel dışı bir yoldan çözüldüğünü doğrulayın.

Proxy kimlik bilgileri ifade edilemez

setHttpProxy(ProxyInfo) arayüzü bir HTTP veya SOCKS proxy'sine yönlendirir ve bir PAC URL'si hedef başına ikisi arasında seçim yapabilir. Ne ProxyInfo ne de PAC biçimi kullanıcı adı ve parola taşır, bu yüzden kimlik doğrulama gerektiren proxy platform API'sinin dışında kalır. Buna ihtiyaç duyan uygulamalar genellikle bir kullanıcı alanı yığını, tun2socks veya benzer bir motor gömer ve 407 meydan okumasına kendileri yanıt verir.

Bu seçimin sonuçları vardır. Kullanıcı alanı yığını yalnızca ona yönlendirdiğiniz trafiği görür, bu yüzden aynı tanımlayıcı sınırı içinde yaşamalıdır ve kendi yukarı bağlantı soketi için aynı protect() gereksinimini devralır. protect()'i atlarsanız tünel kendi taşımasını yakalar; bu, ilk paketten sonra takılan bir el sıkışma olarak görünür. Kimlik bilgisi isteyen bir proxy'ye karşı test edin, çünkü açık proxy platform yolunda geçer ve hiçbir şey kanıtlamaz.

Uygulama listeleri ve DNS de bildirimdir

Builder'da hem addAllowedApplication hem addDisallowedApplication vardır ve birbirlerini dışlarlar: ikisini birden çağırmak istisna fırlatır. Her durumda liste arayüz kurulumunda kullanıcı başına uygulanır, bu yüzden iş profili uygulaması sizin tünelinizle değil iş profili tüneliyle yönetilir. Hiçbir API'nin vermediği şey başka bir uygulamanın kararı üzerindeki kontroldür: dışarıdan paketi tünelinize itemezsiniz ve zaten etkin bir VPN'i kapatamaz veya yeniden yapılandıramazsınız.

DNS aynı kalıbı izler. addDnsServer bir resolver adresi duyurur; uygulamanızın sorgulara yanıt vermesine izin vermez. Adları kendiniz çözmek istiyorsanız bir resolver çalıştırın ve adresini tünele yönlendirin. Sabit bir ana bilgisayar adına DoT veya DoH kullanan uygulamalar duyurduğunuz adresi atlayabilir, bu yüzden sorgu yolunu da yakalamıyorsanız ad çözümlemeyi en iyi çaba olarak görün.

Manifest, always-on ve dört adımlı test

Uygunluk manifestte bildirilir: BIND_VPN_SERVICE, android.net.VpnService intent filtresi ve tünel arka planda kalacaksa ön plan hizmeti. Always-on VPN ayrıca temiz bir onRevoke gerektirir, çünkü sistem onu kullanıcı ayarları değiştirdiğinde veya başka bir uygulama kontrolü devraldığında çağırır.

Kontrolleri sırayla yapın ve ilk hatada durun. Birincisi, builder'a verilen adres, rota ve DNS listelerini dökün. İkincisi, establish()'in bir tanımlayıcı döndürdüğünü ve taşıma soketinin korunduğunu doğrulayın. Üçüncüsü, dahil edilmiş bir önek içinde bir ve dışlanmış bir önek içinde bir hedef isteyin. Dördüncüsü, yalnızca sizin resolver'ınızın çözebileceği bir ana bilgisayar adı sorarak hangi resolver'ın gerçekten yanıt verdiğini kontrol edin.

Tamamlanmış bir el sıkışma sonraki adımların hiçbirini kanıtlamaz. Her kontrol tek bir katmanı yalıtır, bu yüzden ikinci adımdaki başarı dördüncü hakkında hiçbir şey söylemez.

VpnService.Builder başvurusu builder'ın tüm yüzeyini listeler. Bunun ötesinde ihtiyaç duyduğunuz her şey başka bir API, başka bir uygulama veya kendi kullanıcı alanı yığınınızdır ve bu bir tasarım kararıdır, bölünmüş tünel hatası değil.

İlgili makaleler