Dodali ste domen na listu dozvoljenih, upit stiže do vaše aplikacije, poklapač vraća dozvoljeno, a stranica se ipak nikad ne učita. U tom trenutku većina počinje da prepisuje poklapač i dodaje poređenja sa džokerima. Po mom iskustvu poklapač je obično ispravan, a kvar leži jedan sloj niže: u DNS odgovoru koji ste sintetizovali, u ruti koju ste instalirali ili u soketu koji ste koristili za prosleđivanje upita. Lista je lakši deo; put paketa je mesto gde se liste dozvoljenih lome.

Poklapač je retko krivac

Prvo što treba razdvojiti je blokirano od pokvarenog. Blokirano ime treba brzo i vidljivo da padne, jer pregledač dobije odgovor da ime ne postoji i zaustavi se. Pokvareno ime se smrzava, ponavlja pokušaje preko IPv6, prelazi na drugi transport i ostavlja vas sa pokretnim indikatorom. Ako vidite pokretni indikator, vaša lista dozvoljenih verovatno odgovara nečim na šta klijent ne može da reaguje.

Prazan A zapis je klasična greška. Vraćanje NOERROR sa nula odgovora izgleda kao valjan odgovor, pa ga stub rezolver prihvati, pregledač pokuša ponovo, pokuša AAAA, pokuša drugi rezolver i odustane mnogo kasnije. Kôd odgovora 3, to jest NXDOMAIN, sa ponovljenim odeljkom pitanja i kopiranim ID-om transakcije završava razgovor odmah. Koristite ga za svako ime koje namerno odbijate.

IPv6 zaslužuje istu odluku, a ne podrazumevanu vrednost. Ako na A odgovorite NXDOMAIN a AAAA propustite, klijent može doći do blokiranog imena preko IPv6 i filter propušta. Neke implementacije na blokirane AAAA upite odgovaraju loopback adresom kako bi veza odmah pala umesto da pređe na rezervu. Izaberite jednu politiku, primenite je na oba tipa zapisa i beležite oba.

Ruta koja hvata sve poseduje sve

Dizajn samo sa DNS-om nikad ne dodaje addRoute("0.0.0.0", 0), pa u TUN interfejs ulaze samo upiti, a sve ostalo nastavlja da koristi donju mrežu. To je siguran oblik i objašnjava zašto neke liste dozvoljenih rade na Wi-Fi mreži a padaju na mobilnoj.

U trenutku kada postoji podrazumevana ruta, svaki tok je vaš. TCP paket koji stigne na interfejs i nije ni prosleđen ni odgovoren stoji u redu dok klijentu ne istekne vreme, a greške nema za beleženje jer ništa nije pogrešilo. Gledao sam kako neko provede popodne na pokvarenoj listi dozvoljenih koja je zapravo bila prosleđivač koji nedostaje za port 443. Beležite protokol i odredište svakog paketa koji odlučite da odbacite.

Soket rezolvera mora da izađe iz tunela

Prosleđivanje je mesto sledeće zamke. Rezolveri operatera često žive na privatnoj adresi do koje tunel ne doseže, pa upit koji prosledite ode nikuda i aplikacija prijavi istek vremena čitanja. Šaljite odobrene upite rezolveru za koji znate da je dostupan i prvo predajte taj soket funkciji VpnService.protect(). Nezaštićen soket vraća upit natrag u vaš sopstveni tunel, gde ponovo stigne do aplikacije i kruži dok ne opali tajmer.

Kvar izgleda identično kao prekid mreže, zato tako dugo preživljava u prijavama grešaka. Držite brojače poslatih upita i primljenih odgovora: ako prvi broj raste a drugi ostaje na nuli, gledate u soket, ne u listu.

Veličina i kontrolne sume padaju bez poruke

Tiha odbacivanja dolaze i od veličine. DNS odgovor sa velikim skupom odgovora ili TCP rukovanje sa izdašnim opcijama može premašiti MTU puta koji nikad niste izričito postavili; fragment nestaje uzvodno i klijent ili ponovi pokušaj sa manjim ili prestane da pokušava. Postavljanje MTU-a interfejsa na 1280 je konzervativan izbor koji preživljava većinu mobilnih puteva, a izričitost je bolja od nasleđivanja podrazumevane vrednosti koju niko nije izmerio.

Ako sami gradite pakete, kontrolna suma je drugi tihi ubica. UDP kontrolna suma izračunata preko pseudozaglavlja koje izostavlja dužinu UDP-a ili polje protokola daje paket koji na vašoj strani izgleda ispravno, a primalac ga odbacuje bez traga. Uporedite svoje pseudozaglavlje sa specifikacijom polje po polje i ispišite izračunatu kontrolnu sumu za jedan poznat tok dok otklanjate grešku.

Šta VpnService neće uraditi za vas

Dve granice vredi znati pre nego što dizajnirate oko njih. Nijedna obična aplikacija ne može instalirati sistemski proksi ili PAC datoteku izvan Wi-Fi veze, a taj deo se nije promenio. Put po aplikaciji jeste: pre API-ja 29 VpnService.Builder uopšte nije mogao nositi proksi, a od API-ja 29 setHttpProxy(ProxyInfo.buildPacProxy(uri)) daje platformi PAC skriptu za procenu za VPN mrežu. Procenjujte pravila u sopstvenom kodu kada ciljate starije API-je ili kada PAC model ne može izraziti pravilo. UDP takođe nije besplatan: pregledači šalju samo TCP kroz SOCKS proksi, a većina SOCKS5 klijenata nikad ne implementira UDP ASSOCIATE, pa dizajn zasnovan na proksiju odbacuje ili propušta UDP dok TCP izgleda zdravo.

Ta druga granica razlog je zašto protokol zasnovan na UDP-u može raditi na običnoj mreži i pasti onog trenutka kad se vaš VPN poveže. Ako se od tunela očekuje da nosi UDP, prosleđivač mora implementirati put prosleđivanja za njega, ne samo TCP put sa drugim tipom soketa.

Proveravajte ovim redom

Prođite listu redom i zaustavite se na prvom koraku koji padne, jer je svaka kasnija provera šum dok prethodna ne drži.

  1. Navedite instalirane rute i potvrdite da li paketi koji nisu DNS uopšte ulaze u TUN interfejs.
  2. Beležite ime upita, odluku i kôd odgovora za jedno blokirano i jedno odobreno ime.
  3. Potvrdite da je soket rezolvera zaštićen i da izabrani rezolver odgovara iz unutrašnjosti tunela.
  4. Potvrdite MTU interfejsa i kontrolnu sumu jednog ručno sastavljenog odgovora.
  5. Ponovite istu stranicu na Wi-Fi i mobilnoj mreži, jer se rezolveri operatera i MTU puta razlikuju.

Ako svih pet drži a stranica se još smrzava, sledeći osumnjičeni je sam prosleđivač: uporedite snimljeni zahtev sa snimljenim odgovorom i tražite broj bajtova koji nedostaje ili napola zatvoren soket. Referenca za VpnService.Builder pokriva ugovore o ruti, DNS-u i MTU-u, a protect() je odvojen poziv VpnService, a ne opcija builder-a; povezan interfejs znači samo da je prvi ugovor ispunjen.

Povezani članci