Dodali ste domenu na popis dopuštenih, upit stigne do vaše aplikacije, uspoređivač vrati dopušteno, a stranica se ipak nikad ne učita. U tom trenutku većina ljudi počne prepisivati uspoređivač i dodavati usporedbe s džokerima. Prema mom iskustvu uspoređivač je obično ispravan, a kvar leži jedan sloj niže: u DNS odgovoru koji ste sintetizirali, u ruti koju ste instalirali ili u socketu koji ste upotrijebili za prosljeđivanje upita. Popis je lakši dio; put paketa je mjesto gdje se popisi dopuštenih lome.

Uspoređivač je rijetko krivac

Prvo što treba razdvojiti je blokirano od pokvarenog. Blokirano ime treba brzo i vidljivo pasti, jer preglednik dobije odgovor da ime ne postoji i zaustavi se. Pokvareno ime se zamrzava, ponavlja pokušaje preko IPv6, prelazi na drugi prijenos i ostavlja vas s pokretnim indikatorom. Ako vidite pokretni indikator, vaš popis dopuštenih vjerojatno odgovara nečim na što klijent ne može reagirati.

Prazan A zapis klasična je pogreška. Vraćanje NOERROR s nula odgovora izgleda kao valjan odgovor, pa ga stub razrješivač prihvati, preglednik pokuša ponovno, pokuša AAAA, pokuša drugi razrješivač i odustane mnogo kasnije. Kôd odgovora 3, NXDOMAIN, s ponovljenim odjeljkom pitanja i kopiranim ID-om transakcije završava razgovor odmah. Rabite ga za svako ime koje namjerno odbijate.

IPv6 zaslužuje istu odluku, a ne zadanu vrijednost. Ako na A odgovorite NXDOMAIN a AAAA propustite, klijent može doći do blokiranog imena preko IPv6 i filtar propušta. Neke implementacije na blokirane AAAA upite odgovaraju loopback adresom kako bi veza odmah pala umjesto da prijeđe na rezervu. Odaberite jednu politiku, primijenite je na oba tipa zapisa i bilježite oba.

Ruta koja hvata sve posjeduje sve

Dizajn samo s DNS-om nikad ne dodaje addRoute("0.0.0.0", 0), pa u TUN sučelje ulaze samo upiti, a sve ostalo nastavlja koristiti donju mrežu. To je siguran oblik i objašnjava zašto neki popisi dopuštenih rade na Wi-Fi mreži a padaju na mobilnoj.

U trenutku kad postoji zadana ruta, svaki tok je vaš. TCP paket koji stigne na sučelje i nije ni proslijeđen ni odgovoren stoji u redu dok klijentu ne istekne vrijeme, a pogreške nema za bilježenje jer ništa nije pogriješilo. Gledao sam kako netko provede poslijepodne na pokvarenom popisu dopuštenih koji je zapravo bio prosljeđivač koji nedostaje za port 443. Bilježite protokol i odredište svakog paketa koji odlučite odbaciti.

Socket razrješivača mora izaći iz tunela

Prosljeđivanje je mjesto sljedeće zamke. Razrješivači operatera često žive na privatnoj adresi do koje tunel ne doseže, pa upit koji proslijedite ode nikamo i aplikacija prijavi istek vremena čitanja. Šaljite odobrene upite razrješivaču za koji znate da je dostupan i prvo predajte taj socket funkciji VpnService.protect(). Nezaštićen socket vraća upit natrag u vaš vlastiti tunel, gdje ponovno 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 pogrešaka. Držite brojače poslanih upita i primljenih odgovora: ako prvi broj raste a drugi ostaje na nuli, gledate u socket, ne u popis.

Veličina i kontrolne sume padaju bez poruke

Tiha odbacivanja dolaze i od veličine. DNS odgovor s velikim skupom odgovora ili TCP rukovanje s izdašnim opcijama može premašiti MTU puta koji nikad niste izričito postavili; fragment nestaje uzvodno i klijent ili ponovi pokušaj s manjim ili prestane pokušavati. Postavljanje MTU-a sučelja na 1280 konzervativan je izbor koji preživljava većinu mobilnih puteva, a izričitost je bolja od nasljeđivanja zadane vrijednosti koju nitko nije mjerio.

Ako sami gradite pakete, kontrolna suma drugi je tihi ubojica. UDP kontrolna suma izračunata preko pseudozaglavlja koje izostavlja duljinu UDP-a ili polje protokola daje paket koji na vašoj strani izgleda ispravno, a primatelj ga odbacuje bez traga. Usporedite svoje pseudozaglavlje sa specifikacijom polje po polje i ispišite izračunatu kontrolnu sumu za jedan poznati tok dok otklanjate pogrešku.

Što VpnService neće učiniti za vas

Dvije granice vrijedi znati prije nego što dizajnirate oko njih. Nijedna obična aplikacija ne može instalirati sistemski proxy ili PAC datoteku izvan Wi-Fi veze, a taj se dio nije promijenio. Put po aplikaciji jest: prije API-ja 29 VpnService.Builder uopće nije mogao nositi proxy, a od API-ja 29 setHttpProxy(ProxyInfo.buildPacProxy(uri)) daje platformi PAC skriptu za procjenu za VPN mrežu. Procjenjujte pravila u vlastitom kodu kada ciljate starije API-je ili kada PAC model ne može izraziti pravilo. UDP također nije besplatan: preglednici šalju samo TCP kroz SOCKS proxy, a većina SOCKS5 klijenata nikad ne implementira UDP ASSOCIATE, pa dizajn zasnovan na proxyju 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, prosljeđivač mora implementirati put prosljeđivanja za njega, ne samo TCP put s drugim tipom socketa.

Provjeravajte ovim redom

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

  1. Navedite instalirane rute i potvrdite ulaze li paketi koji nisu DNS uopće u TUN sučelje.
  2. Bilježite ime upita, odluku i kôd odgovora za jedno blokirano i jedno odobreno ime.
  3. Potvrdite da je socket razrješivača zaštićen i da odabrani razrješivač odgovara iz unutrašnjosti tunela.
  4. Potvrdite MTU sučelja i kontrolnu sumu jednog ručno sastavljenog odgovora.
  5. Ponovite istu stranicu na Wi-Fi i mobilnoj mreži, jer se razrješivači operatera i MTU puta razlikuju.

Ako svih pet drži a stranica se još zamrzava, sljedeći osumnjičeni je sam prosljeđivač: usporedite snimljeni zahtjev sa snimljenim odgovorom i tražite broj bajtova koji nedostaje ili napola zatvoren socket. Referenca za VpnService.Builder pokriva ugovore o ruti, DNS-u i MTU-u, a protect() je odvojen poziv VpnService, a ne opcija builder-a; povezano sučelje znači samo da je prvi ugovor ispunjen.

Povezani članci