Mikään VpnServicessä ei sieppaa liikennettä itsestään. Se pyytää järjestelmältä tun-rajapinnan, antaa sille rajapinnalle joukon osoitteita ja reittejä, ja siitä hetkestä lähtien ydin kopioi jokaisen näihin reitteihin sopivan paketin tiedostokuvaukseen, jota sovellus voi lukea. Sovelluksen koodi ei koskaan näe paketteja, joita reitit eivät valinneet, joten tunnelin laajuus on reititystaulukysymys ennen kuin se on ohjelmointikysymys. Siksi sama palvelutoteutus voi niellä jokaisen virtauksen yhdessä puhelimessa ja vain osan toisessa, ja siksi reitin lisääminen joskus korjaa tunnelin, joka näytti rikkinäiseltä. Saat sen, minkä ilmoitit, miinus kaikki, mitä rakentaja hiljaa hylkäsi.

Reitit päättävät, mitkä paketit saapuvat

Builder.addRoute(prefix, prefixLength) asentaa etuliitteen VPN-verkon reititystauluun. Järjestelmä kohtelee tätä verkkoa oletuksena laajuuden sovelluksille, joten sen merkintöjä tarkastellaan ennen fyysisen verkon oletusreittiä ja sopiva etuliite riittää ohjaamaan virtauksen toisaalle. Siksi reitti 0.0.0.0/0:lle ottaa IPv4:n kokonaan, mukaan lukien tulostin, cast-kohde ja reitittimen hallintasivu.

Asiakkaat, jotka haluavat tämän kattavuuden poistamatta fyysistä oletusmerkintää, käyttävät sen sijaan paria 0.0.0.0/1 ja 128.0.0.0/1. Kaksi täsmällisempää reittiä voittaa oletusreitin, yhdessä ne kattavat koko osoiteavaruuden, ja puhelimen oma oletusmerkintä jää tauluun soketeille, jotka ovat yhä sidottuja fyysiseen verkkoon.

Osoitteet ja DNS-merkinnät tulevat samasta rakentajasta ja vastaavat eri kysymykseen. addAddress antaa rajapinnalle osoitteen etuliitteen pituudella, ja addDnsServer asentaa ratkaisijan, jota laajuuden sovellukset kysyvät rajapinnan kautta. Kumpikin perhe voi istua yhdellä rajapinnalla, joten vain IPv4-reittien joukko IPv6-osoitteen vieressä on kokoonpano, joka lukee oikein ja vuotaa silti. Jos reitität perheen, jossa rajapinnalla ei ole osoitetta, ytimellä ei ole lähdeosoitetta näille paketeille, eivätkä ne koskaan ilmesty kuvaukseen.

Mitä establish() palauttaa

establish() palauttaa ParcelFileDescriptor:n tai null, kun sovellus ei ole valtuutettu. Null on suostumustila eikä verkkovirhe: VpnService.prepare() on täytynyt jo palauttaa null, tai käyttäjän on täytynyt hyväksyä järjestelmän valintaikkuna ennen kutsua. Suostumus voidaan peruuttaa palvelun toimiessa, ja rajapinta sulkeutuu altasi ilman yhtään takaisinkutsua lukusilmukkaasi.

Kuvaus ei estä, ellet toisin sano, joten luku palaa heti ilman dataa sen sijaan, että säie pysäköitäisiin. Estävälle soketille kirjoitettu silmukka polttaa yhden ytimen, ja silmukka, joka pitää tyhjää lukua kohtalokkaana, repii tunnelin tyhjän sekunnin aikana. Builder.setBlocking(true) muuttaa tätä käyttäytymistä, ja hinta on säie, joka odottaa luvun sisällä.

Reitti- ja osoiteargumentit validoidaan LinkAddress-arvoina, ja multicast-kohteet kuten 224.0.0.0/4 hylätään suoraan. Pisteestä pisteeseen -tun-rajapinnalla ei myöskään ole broadcast-toimialuetta, joten multicast-löytäminen sen kautta vaatii eri suunnittelun eikä yhtä reittiä lisää. Viite VpnService.Builder on lista, joka tarkistetaan ennen kuin päättelet kutsun jääneen huomiotta.

Sovelluskohtainen laajuus kaventaa joukkoa, ei tunnelia

API 21:stä lähtien rakentaja hyväksyy addAllowedApplication:n ja addDisallowedApplication:n, ja kaksi listaa ovat toisensa poissulkevia yhdessä rakentajassa. Sallittujen lista saa tunnelin olemaan näille paketeille, kun kaikki muu pitää fyysisen verkon; kiellettyjen lista nappaa kaiken paitsi nimetyt paketit, mitä asiakas tarjoaa jaettuna tunnelointina. Ennen API 21:tä ei ole lainkaan alustamekanismia, ja sovelluskohtainen käyttäytyminen tuli kolmannen osapuolen asiakkaista, jotka suodattivat UID:n mukaan omassa välittäjessään. Ero on tärkeä virheenkorjauksessa, koska yhden paketin sallittujen listalla varustettu sovelluskohtainen tunneli tuottaa tuskin lainkaan liikennettä, ja se on oikeaa käyttäytymistä, ei rikkinäinen reitti.

Laajuus mikä tahansa, sovelluksesi VPN-palvelimelle avaama soketti ei saa kulkea rakentamansa tunnelin läpi. VpnService.protect(socket) sitoo tämän soketin taustaverkkoon, jotta sen paketit ohittavat tun-laitteen. Jos jätät kutsun väliin, kättelyn nielee rajapinta, jonka piti nostaa se.

VpnService.setUnderlyingNetworks sulkee silmukan kertomalla järjestelmälle, mikä fyysinen verkko kantaa tunnelin. Tämä arvo määrää, miten VPN raportoi yhteyden muille sovelluksille, ja null tai vanhentunut arvo on tavallinen syy yhdistettyyn tunneliin, jota puhelimen muu osa pitää offline-tilassa. Päivitä se, kun taustaverkko vaihtuu, ei vain käynnistyksessä.

Tarkistussummat ja MTU: missä oikea reitti silti epäonnistuu

Kun paketit saapuvat, kaksi pakettitason yksityiskohtaa ratkaisee, toimiiko mikään päästä päähän. Ensimmäinen on lähdeosoite: usean rajapintaosoitteen kanssa ydin voi lähettää paketteja, jotka kantavat ensimmäistä, joten otsikoita uudelleen kirjoittavan välittäjän on korjattava osoite ja sen kattava tarkistussumma.

Toinen on tarkistussumman laajuus. Kun sovellus rakentaa TCP- tai UDP-paketit itse, tarkistussumma kattaa pseudootsikon, jossa on lähdeosoite, kohdeosoite, protokollanumero ja kuljetuksen pituus, ja minkä tahansa niistä pois jättäminen tuottaa paketteja, jotka saapuvat ja pudotetaan. Tämä vika näyttää aikakatkaisulta vastauksen jälkeen, jota ei koskaan tule, mikä lähettää useimmat takaisin reitteihin. setMtu kiinnittää rajapinnan MTU:n, ja jokainen luku palauttaa täsmälleen yhden täydellisen IP-paketin, joten tavuvirtaa varten kirjoitettu puskuri pilkkoo jäsennyksesi, ei pakettia.

Tarkistuskierros, joka erottaa kerrokset

Löytääksesi, missä laajuus meni pieleen, testaa kerrokset järjestyksessä. Kysy laitteelta, mitä reittejä VPN-verkko todella pitää, tarkista sitten, näkyykö virtaus tunnettuun osoitteeseen lukuna kuvauksessa, tarkista sitten, onko paketti, jonka välittäjäsi lähettää, hyvin muodostettu. Reittiongelma ei näytä kuvauksessa mitään, kun taas tarkistussummaongelma näyttää paketin, joka saapuu ja katoaa.

Jos kuvaukseen ei saavu mitään, epäilty on reittijoukko eikä lukija: vahvista etuliitteet, vahvista että samassa perheessä on osoite ja vahvista että sovellus on asettamasi laajuuden sisällä. Jos paketit saapuvat kuvaukseen mutta mitään ei tule takaisin, tutki protect() ja taustaverkon arvo ennen kuin kosket reittiin uudelleen. Jos kaukopää raportoi viallisia paketteja, tarkistussumma ja MTU ovat paikat, joihin katsoa. Yksi koe kerrosta kohden säästää iltapäivän arvailua.

Aiheeseen liittyvät artikkelit