Android 10 ve sonrasında /proc/net/tcp dosyasını açan uygulama, socket tablosu yerine erişim reddi alır. VPN arayüzü bunu umursamaz: paketler gelmeye devam eder, çünkü tünel bir yönlendirme kararıdır, dosya izni değil. Değişen şey daha dar bir sorunun yanıtıdır: «bu bağlantı hangi uygulamaya ait?» Yerine geçen ConnectivityManager.getConnectionOwnerUid, desteklenen bağlantı başına sorgu, ve eski alışkanlıkla yeni API arasındaki seçim, gerçekte üç işten hangisine sahip olduğunuza bağlıdır: paket almak, akışı atfetmek veya kullanımı toplamak.

Sahip sorusuna iki yanıt

API 29'dan önce ayrıcalıklı veya root bir süreç çekirdeğin socket tablolarını okuyabilir, dörtlüyü eşleştirebilir ve sahip UID'yi öğrenebilirdi. Bu, tek bir dosyada cihaz çapında bir envanter veriyordu. API 29'dan itibaren dosya sistemi görünümü kısıtlanmıştır ve desteklenen yol, protokol, yerel adres ve uzak adresle bağlantı başına sorgudur.

QuestionLegacy socket tablesgetConnectionOwnerUid
Who owns this flow?Scan and match the tupleAsk once per tuple
Device-wide inventory?Yes, when readableNo, one flow at a time
Historical usage?NoNo; that is NetworkStatsManager
Works without root?No on modern releasesYes, for authorized callers

Karşılaştırma «eskiye karşı yeni» değildir. Bunlar, eskiden tek bir okunabilir dosyanın karşıladığı, şimdi ise üç farklı sözleşmeye sahip üç farklı arayüzün karşıladığı üç farklı iştir.

Yerel adres uygulamanın ucu

Yöntem imzası bir protokol, yerel socket adresi ve uzak socket adresi alır. «Yerel», bağlantıda uygulamanın tarafıdır; incelediğiniz anda paketin kaynağı olan uç değildir. Uzak sunucudan uygulamaya geri dönen bir paketin kaynağı ve hedefi bu tanıma göre terstir.

ConnectivityManager cm = getSystemService(ConnectivityManager.class);
int uid = cm.getConnectionOwnerUid(
    OsConstants.IPPROTO_TCP, appLocalAddress, appRemoteAddress);

Bu yön hatası, çalışan bir sorgunun yanlış yanıt ya da hiç yanıt vermemesinin en yaygın nedenidir. Çağrıdan önce iki ucu da günlüğe kaydedin ve çifti uygulamanın gerçekten açtığı bağlantıyla doğrulayın. Adres ailesi de önemlidir: IPv4 ile eşlenmiş bir adres ile yerel IPv6 adresi farklı tuple'lardır; aynı bağlantı noktalarındaki TCP ve UDP akışları da öyledir.

Yetkilendirme ve bilinmeyen sonuçlar sözleşmenin parçası

Sorgu, ilgili kullanıcının etkin VPN uygulaması dahil, yetkili çağıranlarla sınırlıdır. İlgisiz bir izleme uygulaması başka bir profilin bağlantılarını sayabileceğini varsayamaz ve yetkisiz bir çağrı dostça bir hata yerine güvenlik istisnası fırlatabilir. İki sonucu da açıkça ele alın.

Eksik sahip bir paket adı değildir. Akış, paket ile sorgu arasında kapanmış olabilir, tuple eksik olabilir ya da çağıranın bilmesine izin verilmemiş olabilir. İlk başarılı yanıtı önbelleğe alıp sonra yeniden kullanmak, yeni bir bağlantıyı eski bir uygulamaya atfeder; bu, bilinmiyor diye raporlamaktan daha kötüdür.

Atıf başarısız olduğunda trafiğin yine de bir karara ihtiyacı vardır: politikanın gerektirdiği yerde engelleyin, yalnızca anladığınız bir kapsama izin verin ya da boşluğu görünür kılın. Bu yedek yol tasarıma aittir, bir yoruma değil.

Muhasebe başka bir soru

NetworkStatsManager kullanımı kendi erişim kurallarına göre raporlar. Bir UID'nin bir dönemde ne kadar aktardığını söyleyebilir; rastgele bir canlı paketin sahibini söyleyemez. Ağ yetenekleri bir ağın özelliklerini anlatır, socket dizinini değil. Üçünü karıştırmak tutarlı görünen ve olmayan panolar üretir.

Hangi uygulamaların tüneli kullandığını belirlemenin basit durumu için Android'in desteklenen izinli ve yasaklı uygulama listeleri politikayı zaten hiçbir kazıma yapmadan ifade eder. Akış başına atfı gerçekten ihtiyaç duyan durumlara ayırın ve yön, izinler ve bilinmeyen durumları birlikte ele alan bakımlı bir uygulama için bütçe ayırın.

Aracı işe göre seçin, sonra kenarları test edin

Gereksinim tünel seçimi ise platform listesini kullanın. Canlı atıf ise sahip sorgusunu kullanın ve yanıtlanamayan her tuple'ı bilinmiyor sayın. Geçmiş toplamlar ise stats API'yi kullanın. Ardından naif uygulamaları kıran üç kenarı test edin: ters yönde bir paket, sorgudan önce kapanan bir akış ve etkin VPN olmayan bir çağıran.

Bunların hiçbiri SELinux'u devre dışı bırakmayı, telefonu root'lamayı veya çekirdek tablolarını küresel olarak okunabilir yapmayı gerektirmez. Kısıt tam da amaçtır: platform atfı bir sözleşmenin arkasına taşıdı, böylece yanıt yalnızca meşru olarak ihtiyaç duyan bileşene ulaşır, başkasına değil.

İlgili makaleler