Zakaj Android VpnService prestreže le del prometa in ne vsega
Poti, vnosi DNS in obseg po aplikacijah odločajo, kateri paketi prispejo do naprave tun, zakaj lokalne naprave izginejo in kaj graditelj zavrača.
Nič v VpnService ne prestreže prometa samo po sebi. Od sistema zahteva vmesnik tun, temu vmesniku preda niz naslovov in poti, in od tega trenutka jedro kopira vsak paket, ki ustreza tem potem, v datotečni deskriptor, ki ga aplikacija lahko bere. Koda aplikacije nikoli ne vidi paketov, ki jih poti niso izbrale, zato je obseg tunela vprašanje usmerjevalne tabele, preden postane programsko vprašanje. Zato lahko ista izvedba storitve pogoltne ves tok na enem telefonu in le del na drugem, in zato dodajanje poti včasih popravi tunel, ki je bil videti pokvarjen. Dobite tisto, kar ste deklarirali, minus vse, kar je graditelj tiho zavrnil.
Poti odločajo, kateri paketi prispejo
Builder.addRoute(prefix, prefixLength) namesti predpono v usmerjevalno tabelo omrežja VPN. Sistem to omrežje obravnava kot privzeto za aplikacije v obsegu, zato se njegovi vnosi pregledajo pred privzeto potjo fizičnega omrežja in ujemajoča se predpona zadostuje za preusmeritev toka. Zato pot za 0.0.0.0/0 prevzame IPv4 v celoti, vključno s tiskalnikom, ciljem cast in skrbniško stranjo usmerjevalnika.
Odjemalci, ki želijo to pokritost brez brisanja fizičnega privzetega vnosa, namesto tega uporabijo par 0.0.0.0/1 in 128.0.0.0/1. Dve bolj specifični poti premagata privzeto pot, skupaj pokrivata ves naslovni prostor, in lastni privzeti vnos telefona ostane v tabeli za vtičnice, ki so še vedno vezane na fizično omrežje.
Naslovi in vnosi DNS prihajajo od istega graditelja in odgovarjajo na drugo vprašanje. addAddress da vmesniku naslov z dolžino predpone, addDnsServer pa namesti razreševalnik, ki ga bodo aplikacije v obsegu poizvedovale prek vmesnika. Obe družini lahko sedita na enem vmesniku, zato je niz poti samo IPv4 ob naslovu IPv6 konfiguracija, ki se bere pravilno in vseeno pušča. Če usmerjate družino, v kateri vmesnik nima naslova, jedro nima izvornega naslova za te pakete in ti se nikoli ne pojavijo pri deskriptorju.
Kaj vrne establish()
establish() vrne ParcelFileDescriptor, ali null, ko aplikacija ni pooblaščena. Null je stanje soglasja in ne omrežna napaka: VpnService.prepare() je moral že vrniti null, ali pa je moral uporabnik pred klicem odobriti sistemsko pogovorno okno. Soglasje je mogoče preklicati med delovanjem storitve, in vmesnik se zapre pod vami brez kakršnega koli povratnega klica v vašo zanko branja.
Deskriptor ni blokirajoč, razen če rečete drugače, zato branje vrne takoj brez podatkov, namesto da bi parkiralo nit. Zanka, napisana za blokirajočo vtičnico, zažge eno jedro, zanka, ki prazno branje šteje za usodno, pa raztrga tunel v eni nedejavni sekundi. Builder.setBlocking(true) spremeni to vedenje, cena pa je nit, ki čaka znotraj branja.
Argumenti poti in naslova se preverjajo kot vrednosti LinkAddress, multicast cilji, kot je 224.0.0.0/4, pa se zavrnejo takoj. Vmesnik tun od točke do točke tudi nima domene oddajanja, zato odkrivanje multicast prek njega zahteva drugačno zasnovo, ne le še eno pot. Referenca VpnService.Builder je seznam, ki ga je treba preveriti, preden sklepate, da je bil klic prezrt.
Obseg po aplikacijah zoži niz, ne tunela
Od API 21 graditelj sprejema addAllowedApplication in addDisallowedApplication, oba seznama pa se v enem graditelju medsebojno izključujeta. Seznam dovoljenih ustvari tunel za te pakete, medtem ko vse ostalo ohrani fizično omrežje; seznam prepovedanih ujame vse razen imenovanih paketov, kar odjemalec ponuja kot razdeljeno tuneliranje. Pred API 21 ni nobenega platformskega mehanizma, vedenje po aplikacijah pa je prihajalo od odjemalcev tretjih strani, ki so filtrirali po UID v svojem posredniku. Razlika je pomembna pri odpravljanju napak, ker tunel po aplikacijah s seznamom dovoljenih z enim paketom skoraj ne ustvari prometa in to je pravilno vedenje, ne pokvarjena pot.
Ne glede na obseg vtičnica, ki jo vaša aplikacija odpre proti strežniku VPN, ne sme potovati skozi tunel, ki ga gradi. VpnService.protect(socket) to vtičnico veže na spodnje omrežje, da njeni paketi obidejo napravo tun. Če klic izpustite, rokovanje pogoltne vmesnik, ki bi ga moral dvigniti.
VpnService.setUnderlyingNetworks sklene zanko tako, da sistemu pove, katero fizično omrežje nosi tunel. Ta vrednost določa, kako VPN poroča o povezljivosti drugim aplikacijam, in vrednost null ali zastarela je običajen vzrok za povezan tunel, ki ga preostali telefon obravnava kot brez povezave. Posodobite jo, ko se spodnje omrežje spremeni, ne le ob zagonu.
Kontrolne vsote in MTU: kjer pravilna pot vseeno ne uspe
Ko paketi prispejo, dve podrobnosti na ravni paketa odločita, ali kaj deluje od konca do konca. Prva je izvorni naslov: pri več naslovih vmesnika lahko jedro pošlje pakete, ki nosijo prvega, zato mora posrednik, ki prepisuje glave, popraviti naslov in kontrolno vsoto, ki ga pokriva.
Druga je obseg kontrolne vsote. Ko aplikacija sama gradi pakete TCP ali UDP, kontrolna vsota pokriva psevdo-glavo z izvornim naslovom, ciljnim naslovom, številko protokola in dolžino prenosa, in izpustitev katerega koli od njih da pakete, ki prispejo in se zavržejo. Ta napaka je videti kot časovna omejitev po odgovoru, ki nikoli ne pride, kar večino ljudi pošlje nazaj k potem. setMtu določi MTU vmesnika, in vsako branje vrne natanko en celoten paket IP, zato bo medpomnilnik, napisan za bajtni tok, razdrobil vaše razčlenjevanje, ne paketa.
Prehod preverjanja, ki loči plasti
Da najdete, kje je obseg šel narobe, preizkusite plasti po vrsti. Vprašajte napravo, katere poti omrežje VPN v resnici drži, nato preverite, ali se tok do znanega naslova pojavi kot branje pri deskriptorju, nato preverite, ali je paket, ki ga pošilja vaš posrednik, dobro oblikovan. Težava s potjo ne pokaže ničesar pri deskriptorju, medtem ko težava s kontrolno vsoto pokaže paket, ki prispe in izgine.
Če nič ne doseže deskriptorja, je osumljenec niz poti in ne bralnik: potrdite predpone, potrdite, da obstaja naslov v isti družini, in potrdite, da je aplikacija v obsegu, ki ste ga nastavili. Če paketi dosežejo deskriptor, a se nič ne vrne, preglejte protect() in vrednost spodnjega omrežja, preden se znova dotaknete poti. Če oddaljena stran poroča o okvarjenih paketih, sta kontrolna vsota in MTU mesti, kamor je treba pogledati. Ena sonda na plast prihrani popoldne ugibanja.