İki yol Android tətbiqinin qarşısına IP interfeysi qoya bilər və hər ikisi çox fərqli sahiblərə malik eyni növ fayl deskriptorunda bitir. Biri VpnService və onun qurucusundan, digəri root shell və /dev/net/tun-dan keçir. Həmin deskriptordakı hər oxuma xarici paket, hər yazma isə daxili paketdir. Yolları ayıran şey siyasətin kimin əlində olduğu, OS yeniləməsindən kimin sağ çıxdığı və marşrut cədvəlinin nə qədərinə toxuna bildiyindir.

Platforma yolunu tut, yalnız etməkdən imtina etdiyi konkret şeyi adlandıra bilirsənsə. Bu imtina adətən TAP, öz tətbiq dəstəndən kənarda tutma və ya freymvorkun heç vaxt açmadığı marşrut qaydasıdır.

Platforma yolunda əmrlər yerinə niyyət bildirirsən. Ən azı bir ünvan, istədiyin marşrutlar, DNS serverləri və istəyə bağlı tətbiq siyahısı verirsən, sonra Android sistem xidməti imtiyazlı quraşdırmanı öz kimliyi altında yerinə yetirir. İnterfeys adını əvvəlcədən heç vaxt öyrənmirsən və onu yaradan ioctl-u heç vaxt vermirsən — məqsəd də elə budur.

IP interfeysi əldə etməyin iki yolu

Root yolu daha köhnə reseptdir. /dev/net/tun faylını açır, IFF_TUN ilə TUNSETIFF çağırır, interfeysi ip link ilə qaldırır və ünvanlarla marşrutları əl ilə əlavə edirsən. Hər addımı düzgün etmək sənin işindir, o cümlədən freymvorkun səssizcə həll edəcəyi addımları. Bir çatışmayan marşrut, ölü serverlə eyni istifadəçi məlumatını verir.

Sazlama nə qədər fərqlidirsə, sazlama da o qədər fərqlidir. Root yolunda ya interfeys mövcuddur, ya da ioctl birbaşa oxuya biləcəyin xəta qaytarıb. Platforma yolunda interfeys yalnız establish() uğurlu olduqdan sonra mövcuddur, ona görə uğursuzluq, cızmaq mümkün olan cihaz qovşağı əvəzinə istisna və ya null deskriptor kimi gəlir.

establish() əslində nə qaytarır

Builder.establish() üç nəticə verir və onlar üç fərqli cavab tələb edir. Deskriptor interfeysin qurulduğunu və istifadə üçün sənin olduğunu bildirir, null sorğunun keçmədiyini, atılan istisna isə sistem xidmətinin onu rədd etdiyini. null ilə uğuru bir boolean-da birləşdirmək, heç vaxt paket daşımayan işlək tunel barədə tətbiqin verdiyi ən geniş yayılmış məlumatdır. Builder sənədi ünvan tələbini göstərir və serveri günahlandırmazdan əvvəl oxumağa dəyər.

İstiqamətləri protokolun deyil, deskriptor müəyyən edir. Oxumalar sənə VPN üçün artıq seçilmiş xarici paketlər verir, yazmalar isə daxili paketləri yenidən interfeysə vurur. Paketləri şifrələyən, doğrulayan və kadrlayan öz nəqliyyatındır, çünki platforma paket sərhədində dayanır.

Binder bir addımdır, JNI başqa oxdur

Builder sorğusu Binder vasitəsilə sistemə keçir və bunun altında haradasa platforma cihazı konfiqurasiya etmək üçün doğma kod çağırır. Bunlar bir çağırışın içində üst-üstə yığılmış iki fərqli mexanizmdir. Binder tətbiqinlə sistem xidməti arasında proseslərarası əlaqədir, JNI isə proses daxilində Java-dan doğma koda körpüdür. Android 9 AOSP ağacını oxumaq yığını hərfi görünüşə salır və daxili sinif adları ilə fayl yollarının buraxılışlar arasında dəyişdiyini yadda saxlamağa dəyər.

Dəyişməyən şey arxalana biləcəyin müqavilədir: builder, onun qaytardığı deskriptor və ətrafındakı xidmət həyat dövrü. Heç bir tətbiq interfeys əldə etmək üçün daxili xidmət əməliyyatı çağırmamalı və ya cihaz qovşağını yenidən yaratmamalıdır. Kodun AOSP sinif adından asılıdırsa, sınaqdan keçirmədiyin buraxılışda sınacaq.

TUN IP daşıyır, TAP Ethernet

TUN IP interfeysidir. TAP Ethernet interfeysidir və bu fərq körpüləmənin ümumiyyətlə mümkün olub-olmadığını həll edir. TUN cihazının MAC ünvanı və yönləndiriləcək Ethernet başlığı yoxdur, ona görə TUN müştərisi marşrutlar necə yazılsa da layer-2 körpüyə qoşula bilməz.

VpnService sənə IP variantını verir; tətbiq səviyyəli VPN-in ehtiyacı budur və xam Ethernet yığını olmadan da onu dəstəkləyə bilir. Dizaynın körpüləmə tələb edirsə, platforma yolu səni ora çatdırmayacaq, root yolu isə yalnız kernel və cihaz icazələri əməkdaşlıq etsə çatdıracaq.

Root yolu hələ də harada qalib gəlir

Üç iş insanları platforma yolundan uzaqlaşdırır. Layer-2 körpüləmə TAP tələb edir. Öz VPN əhatənizdən kənar tətbiqlərin trafikini tutmaq freymvorkun vermədiyi görünürlüyü tələb edir. Builder-ın heç vaxt açmadığı siyasət marşrutlaşdırması, məsələn bir təyinat üçün ayrı cədvəl, özün quraşdırdığın qaydaları tələb edir.

Xərclər sonra gəlir: açılmış bootloader və ya root edilmiş image, altından dəyişən SELinux siyasəti və OTA-dan sonra davranışını dayandıran cihaz. Root edilmiş resept normal tətbiq paylanması ilə göndərilə bilməz, ona görə komandaların çoxu onu məhsul deyil, daxili diaqnostika yolu kimi saxlayır.

Onların arasında seçim

Sahib olduğun koddan deyil, ehtiyac duyduğun interfeysdən başla. Cavab tətbiq əhatəli marşrutlarla TUN cihazıdırsa, platforma yolu daha qısadır və yeniləmələrdən sağ çıxır. Cavab Ethernet kadrları, başqa tətbiqlərin tutulması və ya builder-ın rədd etdiyi marşrut qaydalarıdırsa, root ərazisindəsən və bunu əməliyyat xərci kimi büdcələməlisən.

Mübahisələrin çoxunu həll edən yoxlama: əvvəlcə platforma yolunu qur, establish() nəticəsini uzaq sessiya vəziyyətindən ayrı qeyd et və hər istiqamətdə bir paketi təsdiqlə. Yalnız bundan sonra çatışmayan imkanın dəstəklənən yolu tərk etməyə əsas verdiyinə qərar ver.

Əlaqəli məqalələr