Divi ceļi var novietot IP saskarni Android lietotnes priekšā, un abi beidzas ar viena veida faila deskriptoru ar ļoti atšķirīgiem īpašniekiem. Viens iet caur VpnService un tā builderi, otrs caur root čaulu un /dev/net/tun. Katra lasīšana šajā deskriptorā ir izejoša pakete, un katra rakstīšana ir ienākoša. Ceļus šķir tas, kam pieder politika, kas pārdzīvo OS atjauninājumu un cik daudz maršrutēšanas tabulas tev ļauts aizskart.

Izvēlies platformas ceļu, ja vien nespēj nosaukt konkrēto lietu, ko tā atsakās darīt. Šī atteikšanās parasti ir TAP, uztveršana ārpus tavas lietotņu kopas vai maršrutēšanas noteikums, ko ietvars nekad neizpauž.

Platformas ceļā tu deklarē nolūku, nevis komandas. Tu dod vismaz vienu adresi, vēlamos maršrutus, DNS serverus un neobligātu lietotņu sarakstu, tad Android sistēmas pakalpojums veic privileģēto iestatīšanu savā identitātē. Saskarnes nosaukumu tu nekad neuzzini iepriekš un nekad neizdod ioctl, kas to izveido, un tas ir galvenais.

Divi veidi, kā iegūt IP saskarni

Root ceļš ir vecākā recepte. Tu atver /dev/net/tun, izsauc TUNSETIFF ar IFF_TUN, paceļ saskarni ar ip link un pievieno adreses un maršrutus ar roku. Katrs solis tev jāizdara pareizi, tostarp tie, ko ietvars būtu nokārtojis klusām. Viens trūkstošs maršruts lietotājam dod tādu pašu atskaiti kā miris serveris.

Atkļūdošana atšķiras tikpat daudz kā iestatīšana. Root ceļā saskarne vai nu pastāv, vai tavs ioctl atgriezis kļūdu, ko vari lasīt tieši. Platformas ceļā saskarne pastāv tikai pēc tam, kad establish() izdodas, tāpēc kļūme nāk kā izņēmums vai null deskriptors, nevis kā ierīces mezgls, kurā var rakņāties.

Ko establish() patiešām atgriež

Builder.establish() ir trīs iznākumi, un tiem vajadzīgas trīs dažādas atbildes. Deskriptors nozīmē, ka saskarne ir konfigurēta un tava lietošanai, null nozīmē, ka pieprasījums nav gājis cauri, bet izmests izņēmums nozīmē, ka sistēmas pakalpojums to noraidīja. null un panākumu sapludināšana vienā boolean ir visizplatītākais veids, kā lietotne ziņo par strādājošu tuneli, kas nekad nenes paketi. Builder atsauce norāda adreses prasību, un to ir vērts izlasīt pirms servera vainošanas.

Virzienus nosaka deskriptors, nevis tavs protokols. Lasījumi dod izejošas paketes, kas jau atlasītas VPN, un rakstījumi ievada ienākošas paketes atpakaļ saskarnē. Tavs paša transports šifrē, autentificē un ierāmē šīs paketes, jo platforma apstājas pie paketes robežas.

Binder ir viens lēciens, JNI ir cita ass

Builder pieprasījums šķērso sistēmā caur Binder, un kaut kur zem tā platforma izsauc natīvo kodu, lai konfigurētu ierīci. Tie ir divi dažādi mehānismi, sakrauti vienā izsaukumā. Binder ir starpprocesu komunikācija starp tavu lietotni un sistēmas pakalpojumu, kamēr JNI ir tilts no Java uz natīvo kodu procesa iekšienē. Android 9 AOSP koka lasīšana padara steku burtisku, un ir vērts atcerēties, ka iekšējie klašu nosaukumi un failu ceļi starp laidieniem mainās.

Tas, kas nemainās, ir līgums, uz kuru vari paļauties: builderis, tā atgrieztais deskriptors un ap to esošais pakalpojuma dzīves cikls. Nevienai lietotnei nevajadzētu izsaukt iekšēju pakalpojuma transakciju vai no jauna veidot ierīces mezglu, lai iegūtu saskarni. Ja tavs kods ir atkarīgs no AOSP klases nosaukuma, tas salūzīs laidienā, kuru neesi pārbaudījis.

TUN nes IP, TAP nes Ethernet

TUN ir IP saskarne. TAP ir Ethernet saskarne, un šī atšķirība izšķir, vai tiltēšana vispār ir iespējama. TUN ierīcei nav MAC adreses un nav pārsūtāmas Ethernet galvenes, tāpēc TUN klients nevar pievienoties layer-2 tiltam, lai kā būtu rakstīti maršruti.

VpnService dod tev IP variantu, kas nepieciešams lietotnes līmeņa VPN un ko tas var atbalstīt bez neapstrādāta Ethernet steka. Ja tavs dizains prasa tiltēšanu, platformas ceļš tevi tur neaizvedīs, un root ceļš to darīs tikai tad, ja kodols un ierīces atļaujas sadarbojas.

Kur root ceļš joprojām uzvar

Trīs darbi izstumj cilvēkus no platformas ceļa. layer-2 tiltēšanai vajag TAP. Lai uztvertu lietotņu datplūsmu ārpus tavas VPN apjoma, vajag redzamību, ko ietvars nepiešķir. Uz politiku balstīta maršrutēšana, ko builderis nekad neizpauž, piemēram, atsevišķa tabula vienam galamērķim, prasa noteikumus, ko pats instalē.

Izmaksas nāk vēlāk: atbloķēts bootloader vai rootota kopija, SELinux politika, kas zem tevis kustas, un ierīce, kas pēc OTA pārstāj uzvesties pareizi. Roototu recepti arī nevar izplatīt ar parasto lietotņu izplatīšanu, tāpēc vairums komandu to tur kā iekšēju diagnostikas ceļu, nevis produktu.

Izvēle starp abiem

Sāc no saskarnes, kas tev vajadzīga, nevis no koda, kas tev ir. Ja atbilde ir TUN ierīce ar lietotnei ierobežotiem maršrutiem, platformas ceļš ir īsāks un pārdzīvo atjauninājumus. Ja atbilde ietver Ethernet kadrus, citu lietotņu uztveršanu vai maršrutēšanas noteikumus, ko builderis noraida, tu esi root teritorijā un tev tas jāiekļauj budžetā kā darbības izmaksas.

Pārbaude, kas atrisina lielāko daļu strīdu: vispirms izveido platformas ceļu, pieraksti establish() rezultātu atsevišķi no attālās sesijas stāvokļa un apstiprini vienu paketi katrā virzienā. Tikai tad izlem, vai trūkstošā iespēja attaisno atbalstītā ceļa atstāšanu.

Saistītie raksti