Miski VpnService'is ei püüa liiklust iseenesest. See küsib süsteemilt tun-liidest, annab sellele liidesele hulga aadresse ja marsruute ning sellest hetkest kopeerib kernel iga nende marsruutidega sobiva paketi failideskriptorisse, mida rakendus saab lugeda. Rakenduse kood ei näe kunagi pakette, mida marsruudid ei valinud, seega on tunnelite ulatus marsruutimistabeli küsimus enne, kui see on programmeerimisküsimus. Seetõttu võib sama teenuse teostus ühel telefonil alla neelata iga voolu ja teisel vaid tüki, ja seetõttu parandab marsruudi lisamine mõnikord tunnelit, mis näis katki. See, mis saad, on see, mida deklareerisid, miinus kõik, millest ehitaja vaikselt keeldus.

Marsruudid otsustavad, millised paketid kohale jõuavad

Builder.addRoute(prefix, prefixLength) paigaldab prefiksi VPN-võrgu marsruutimistabelisse. Süsteem kohtleb seda võrku ulatuses olevate rakenduste jaoks vaikimisi võrguna, seega vaadatakse selle kirjed läbi enne füüsilise võrgu vaikimisi marsruuti ja sobivast prefiksist piisab voolu kõrvale juhtimiseks. Seetõttu võtab 0.0.0.0/0 marsruut IPv4 täielikult, kaasa arvatud printer, cast-sihtmärk ja ruuteri haldusleht.

Kliendid, kes seda katvust soovivad ilma füüsilist vaikimisi kirjet kustutamata, kasutavad selle asemel paari 0.0.0.0/1 ja 128.0.0.0/1. Kaks täpsemat marsruuti võidavad vaikimisi marsruudi, koos katavad nad kogu aadressiruumi ja telefoni enda vaikimisi kirje jääb tabelisse nende sokettide jaoks, mis on veel füüsilise võrguga seotud.

Aadressid ja DNS-kirjed tulevad samast ehitajast ja vastavad teisele küsimusele. addAddress annab liidesele aadressi koos prefiksi pikkusega ja addDnsServer paigaldab resolveri, millelt ulatuses olevad rakendused liidese kaudu küsivad. Mõlemad perekonnad võivad ühel liidesel istuda, seega on ainult IPv4 marsruutide komplekt IPv6-aadressi kõrval konfiguratsioon, mis loeb õigesti ja lekib ikkagi. Kui marsruudite perekonda, milles liidesel aadressi pole, pole kernelil nende pakettide jaoks lähteaadressi ja need ei ilmu kunagi deskriptoris.

Mida establish() tagastab

establish() tagastab ParcelFileDescriptor või null, kui rakendus pole volitatud. Null on nõusoleku olek, mitte võrguviga: VpnService.prepare() peab olema juba nulli tagastanud või kasutaja peab olema enne kutset süsteemidialoogi kinnitanud. Nõusoleku saab tühistada teenuse töötamise ajal ja liides sulgub teie all ilma ühegi tagasikutsega lugemistsüklisse.

Deskriptor ei blokeeri, kui te ei ütle teisiti, seega naaseb lugemine kohe ilma andmeteta, selle asemel et lõime parkida. Blokeeriva soketi jaoks kirjutatud tsükkel põletab ühe tuuma ja tsükkel, mis peab tühja lugemist saatuslikuks, rebib tunneli tühja sekundi jooksul maha. Builder.setBlocking(true) muudab seda käitumist ja hinnaks on lõim, mis ootab lugemise sees.

Marsruudi- ja aadressiargumendid valideeritakse LinkAddress väärtustena ning multicast-sihtkohad nagu 224.0.0.0/4 lükatakse kohe tagasi. Punkt-punktilt tun-liidesel pole ka broadcast-domeeni, seega vajab multicast-tuvastus selle kaudu teistsugust lahendust, mitte veel üht marsruuti. Viide VpnService.Builder on nimekiri, mida kontrollida, enne kui järeldate, et kutsest ignoreeriti.

Rakendusepõhine ulatus kitsendab hulka, mitte tunnelit

Alates API 21-st aktsepteerib ehitaja addAllowedApplication ja addDisallowedApplication, ning need kaks nimekirja on ühe ehitaja sees teineteist välistavad. Lubatud nimekiri teeb tunneli nende pakettide jaoks olemasolevaks, samal ajal kui kõik muu säilitab füüsilise võrgu; keelatud nimekiri püüab kõik peale nimetatud pakettide, mida klient pakub jaotatud tunnelina. Enne API 21-t pole platvormimehhanismi üldse ja rakendusepõhine käitumine tuli kolmandate osapoolte klientidest, mis filtreerisid UID järgi oma edastajas. Erinevus loeb silumisel, sest ühe paketi lubatud nimekirjaga rakendusepõhine tunnel tekitab peaaegu üldse liiklust ja see on õige käitumine, mitte katkine marsruut.

Ükskõik milline on ulatus, ei tohi sokkel, mille teie rakendus VPN-serveri vastu avab, liikuda läbi tunneli, mida see ehitab. VpnService.protect(socket) seob selle soketi alusvõrgu külge, et selle paketid jätaksid tun-seadme vahele. Kui kutse vahele jätate, neelab käepigistuse liides, mis pidi selle üles tõstma.

VpnService.setUnderlyingNetworks sulgeb ringi, öeldes süsteemile, milline füüsiline võrk tunnelit kannab. See väärtus määrab, kuidas VPN teistele rakendustele ühenduvusest teatab, ning null või aegunud väärtus on tavaline põhjus ühendatud tunneli puhul, mida ülejäänud telefon peab võrguühenduseta. Uuendage seda alusvõrgu muutumisel, mitte ainult käivitamisel.

Kontrollsummad ja MTU: kus õige marsruut siiski ebaõnnestub

Kui paketid kohale jõuavad, otsustavad kaks paketi tasandi üksikasja, kas miski otsast otsani töötab. Esimene on lähteaadress: mitme liidese aadressi korral võib kernel saata pakette, mis kannavad esimest, seega peab päiseid ümber kirjutav edastaja parandama aadressi ja seda katva kontrollsumma.

Teine on kontrollsumma ulatus. Kui rakendus ehitab TCP või UDP paketid ise, katab kontrollsumma pseudopäise, mis hoiab lähteaadressi, sihtaadressi, protokollinumbrit ja transpordi pikkust, ning ükskõik millise nendest väljajätmine annab paketid, mis kohale jõuavad ja ära visatakse. See tõrge näeb välja nagu aegumine pärast vastust, mis kunagi ei tule, mis saadab enamiku inimesi tagasi marsruutide juurde. setMtu fikseerib liidese MTU ja iga lugemine tagastab täpselt ühe täieliku IP-paketi, seega baitvoole kirjutatud puhver tükeldab teie parsimise, mitte paketi.

Kontrollkäik, mis eraldab kihid

Et leida, kus ulatus viltu läks, testige kihte järjekorras. Küsige seadmelt, milliseid marsruute VPN-võrk tegelikult hoiab, seejärel kontrollige, kas vool tuntud aadressile ilmub deskriptoris lugemisena, seejärel kontrollige, kas pakett, mille teie edastaja välja saadab, on korralikult vormitud. Marsruudiprobleem ei näita deskriptoris midagi, samas kui kontrollsumma probleem näitab paketti, mis kohale jõuab ja kaob.

Kui deskriptorini ei jõua midagi, on kahtlusalune marsruutide komplekt, mitte lugeja: kinnitage prefiksid, kinnitage, et samas perekonnas on aadress, ja kinnitage, et rakendus on teie määratud ulatuse sees. Kui paketid jõuavad deskriptorini, aga midagi ei tule tagasi, uurige protect() ja alusvõrgu väärtust, enne kui uuesti marsruuti puudutate. Kui kauge pool teatab vigastest pakettidest, on kontrollsumma ja MTU kohad, kuhu vaadata. Üks sond kihi kohta säästab pärastlõuna oletusi.

Seotud artiklid