Tunnelit paketit voi pitää tunnelin ulkopuolella kahdella tavalla: suojaamalla kuljetuksen socket tai ottamalla koko sovellus pois VPN:stä. Ne ratkaisevat eri ongelmia, ja laajemman valitseminen siksi, että se on helpompi kytkeä, on juuri se tapa, jolla sovellukset menettävät pääsyn lähiverkkoon ja jaetun DNS:n huomaamatta. Aloita siitä, mikä täytyy jäädä tunnelin ulkopuolelle, ja valitse sitten pienin laajuus, joka sen saavuttaa.

Mitä protect() poistaa tunnelista

VpnService.protect() on socketkohtainen kutsu. Annat sille socketin tai kuvaajan, joka kuljettaa tunnelia, ja Android merkitsee kyseisen socketin niin, että sen liikenne käyttää VPN-rajapinnan sijasta alla olevaa verkkoa. Kaikki muu sovelluksen lähettämä noudattaa edelleen tavallista VPN-reittiä.

Juuri tämä kapea laajuus on pointti. Suojattu socket ei muuta sitä, miten HTTP-asiakkaasi selvittää nimiä, mitä rajapintaa analytiikkakutsusi käyttävät tai mitä myöhemmin avatulle toiselle yhteydelle tapahtuu.

Kolme ehtoa, jotka määräävät laajuuden

Ensimmäinen ehto on, täytyykö vain tunnelin kuljetuksen päästä ulos. Jos sovelluksen muu liikenne kulkee edelleen VPN:n kautta, socketin suojaus on oikea laajuus. Toinen ehto on, hallitsetko socketin luontia. Kirjasto, joka avaa oman socketinsa syvällä sisällä, ei jätä sinulle paikkaa kutsua protect(), ellei se tarjoa koukkua tai hyväksy valmiiksi rakennettua socketia. Kolmas ehto on, täytyykö sovelluksen päästä suoraan lähiverkkoon tai captive portal -sivulle, mikä on eri vaatimus kuin tunnelin pitäminen elossa.

Sovelluksen poissulkeminen addDisallowedApplication()-toiminnolla on karkea työkalu. Se poistaa VPN:stä jokaisen yhteyden, jonka sovellus muodostaa, mukaan lukien ne, joita halusit tarkkailla, ja joillakin laitteilla se muuttaa myös paikallisen löytämisen toimintaa.

Kolmas vaihtoehto on sitoa kuljetus valittuun verkkoon bindProcessToNetwork()- tai socket-tason verkkokahvan avulla. Tästä on hyötyä, kun laitteessa on yhtä aikaa Wi-Fi ja mobiiliyhteys ja haluat tunnelin kulkevan tiettyä ylälinkkiä pitkin.

Kutsu sitä, kun kuljetusta luodaan

Kutsu protect() samassa lohkossa, joka luo kuljetuksen, ennen connect() tai send()-kutsua. Jos kutsu palauttaa false, sulje socket ja anna asetusten epäonnistua; jatkaminen jättää sinulle kuljetuksen, jonka paketit voivat palata omaan rajapintaasi.

Muoto on tarpeeksi pieni pidettäväksi yhdessä paikassa:

DatagramSocket transport = new DatagramSocket();
if (!protect(transport)) {
    transport.close();
    throw new IOException("transport not protected");
}
transport.connect(serverAddress);

Kolme yksityiskohtaa puree tässä. Ensinnäkin,boolean on ainoa signaali, jonka saat, joten kirjaa epäonnistuminen riittävällä kontekstilla, jotta erotat peruutetun suostumuksen hylätystä kutsusta. Toiseksi,protect() kattaa socketin, ei kuvaajan numeroa: jos suljet socketin ja käytät myöhemmin samaa kokonaislukua toiselle socketille, uusi socket ei ole suojattu. Kolmanneksi, kun natiivikirjasto avaa kuljetuksen, suojaa kuvaaja ennen kuin natiivikoodi yhdistää, tai reitti voi olla jo valittu.VpnService-viite on paikka, jossa vahvistat, mitkä ylikuormitukset kohde-API-tasosi todella tarjoaa.

Testaa estetty polku, älä vain onnellista polkua

Vahvista tunnelin ollessa ylhäällä, koska se on ainoa tila, jossa kaksi polkua voivat erota. Lähetä yksi pyyntö suojatun kuljetuksen kautta ja toinen koodipolusta, joka ei koskaan kutsunut protect(), ja vertaa sitten, mitä kaukopää näkee: suojatun yhteyden pitäisi saapua alla oleva verkko lähteenään, kun taas suojaamaton näyttää tunnelin oman osoitteen ja liikuttaa tunnelin tavulaskureita. Laitteessa ss tai netstat näyttää saman jaon ennen kuin mitään lähtee radiosta.

Testaa peruutus erikseen, koska suostumuksen muutos repii rajapinnan irti koskematta socketkoodiisi. Peruuta VPN-suostumus tai pysäytä palvelu, rakenna kuljetus uudelleen ja vahvista, että protect() palauttaa edelleen true ja että kuljetus yhdistää uudelleen, kun suostumus annetaan taas.

Jos suojattu pyyntö seuraa tunnelia silti, suojauskutsu tapahtuu todennäköisesti sen jälkeen, kun socket on jo reititetty. Siirrä sitä aiemmaksi ja testaa uudelleen.

Pidä päätös kirjattuna kuljetuksen asetusten viereen: mitkä socketit on suojattu, mikä sovellusliikenne on suljettu pois ja mitä sovellus tekee, kun suojaus epäonnistuu. Juuri tämä rivi estää myöhempää uudelleenjärjestelyä laajentamasta poissulkemista koko sovellukseen siksi, että yksi testi epäonnistui. Se antaa myös seuraavalle henkilölle tavan tarkistaa aikomus purkamatta manifestia taaksepäin.

Aiheeseen liittyvät artikkelit