V isti zanki VpnService se pojavita dva simptoma in oba sta pripisana isti stvari: bralnik, ki se nikoli ne vrne, in pisanje, ki spodleti z ENOBUFS. To nista različici iste napake. Zataknjeno branje je nesoglasje o nadzoru pretoka z nasprotnikom; neuspešno pisanje je paket, ki ga vmesnik ne bo sprejel. Če ju obravnavate kot eno težavo, boste porabili dan za nastavljanje medpomnilnikov, ki niso bili nikoli vpleteni. Spodnja delitev je, kako se odločim, katero polovico zanke najprej instrumentiram.

Ena zanka, dve neodvisni točki odpovedi

Vaša storitev prebere paket IP iz opisnika datoteke TUN, ga pregleda in zapiše odgovor nazaj v isti opisnik. Vse, kar se na tej poti zlomi, se pokaže pri enem od teh dveh klicev, zato se oba prijavita kot pokvarjen tunel. Klica imata različni pogodbi. Branje čaka, da vam jedro izroči paket, pisanje pa jedru izroči paket, ki ga sme zavrniti.

Branja so lažja polovica za razmišljanje. Branje, ki ne vrne ničesar, ali čaka na promet, ki nikoli ne pride, ali čaka, ker je nasprotnik prenehal pošiljati.

Zataknjeno branje je nesoglasje o nadzoru pretoka

Branje naprave TUN se blokira, dokler paket ni na voljo. To je načrtovano vedenje in zato je nit, parkirana v read, videti običajna na nedejavni povezavi. V zastoj se spremeni, ko vaš lastni sklad TCP še naprej sprejema podatke iz lokalne aplikacije, a nikoli ne napove okna, dovolj velikega, da bi oddaljeni nasprotnik poslal več. Nasprotnik napolni napovedano okno, počaka na ACK in posodobitev okna ter se ustavi. Takrat vaš bralnik nima česa vrniti in aplikacija vidi povezavo, ki je odprta in tiha.

Pogosti vzroki so sklad, ki piše v vtičnico brez sledenja napovedanemu oknu, in drugi, ki po izpraznitvi medpomnilnika pozabi poslati posodobitev okna. Od zunaj so videti enaki: bajti gredo ven, nič se ne vrne, nobena napaka se ne sproži. Blokiranje bralne niti pri razčlenjevanju, razreševanju DNS ali diskovnem I/O ustvari enako obliko simptoma iz nepovezanega razloga, zato pred obtoževanjem nadzora pretoka preverite, da je nit res znotraj read.

Preverite čakalno vrsto pošiljanja nasprotnika in okno, ki ga je nazadnje videl. Če nasprotnik zadržuje podatke, ker je vaše okno nič, je popravek na vaši poti ACK, ne v branju TUN.

ENOBUFS je težava velikosti, ne pomanjkanje medpomnilnika

Pisanje, ki na vmesniku TUN vrne ENOBUFS, običajno zavrne dolžino paketa. Vmesnik ima MTU, večjega paketa ni mogoče vstaviti v čakalno vrsto, in ponovni poskus istega paketa vsakič spodleti enako. Ta determiniranost je namig. Pravo pomanjkanje medpomnilnika izgine, ko pritisk pade, zavrnitev zaradi velikosti pa ne zanima, kako dolgo čakate.

TCP ima mehanizem prav za to in to je korak, ki ga ljudje preskočijo: omejitev MSS. Ko v uporabniškem prostoru sintetizirate segmente, izberete velikost koristnega tovora, in če jo vzamete iz MTU lokalnega vmesnika namesto iz MTU tunela, oddajate segmente, ki jih tunel ne zmore prenesti. Omejite na manjšo od obeh. Omejitev pokriva samo TCP, zato mora prevelik UDP datagram vaša koda razdrobiti ali zavreči.

Med razhroščevanjem beležite dolžino vsakega paketa, ki ga zapišete. Dolžina, pri kateri spodleti, je odgovor in se med poskusi ne bo spremenila.

Tri meritve, ki ločijo primere

Za nobeno od obeh odpovedi ne potrebujete razhroščevalnika. Tri opažanja zadostujejo, da se usmerite v pravi razdelek, in trajajo manj časa kot ponovna gradnja.

What you seeWhere to look
Reader parked, peer send queue empty, last advertised window zeroWindow updates in your ACK path
Write fails on one length and succeeds on a smaller oneMSS clamp and tunnel MTU
Both directions look fine, app still sees no dataProtected socket and routing loop

Če se ujema tretja vrstica, je zanka sama v redu in težava je tam, kjer je tunel ne more videti: nezaščitena transportna vtičnica, ki nosi vaš lastni promet VPN nazaj v tunel, kar se običajno pokaže kot povezava, ki uspe in nato ničesar ne dostavi.

Popravite napeljavo, od katere sta odvisni obe poti

Noben simptom ni vreden preganjanja, dokler vmesnik ni pravilno zgrajen. Klici builder, ki štejejo, so naslov, pot, MTU in soglasje, v tem vrstnem redu:

Builder()
  .addAddress(10.8.0.2, 32)
  .addRoute(0.0.0.0, 0)
  .setMtu(1400)
  .establish()

Nastavite MTU na dejansko vrednost tunela, namesto da bi ga pustili na tistem, kar je uporabil primer. Vse, kar pozneje napišete, je omejeno s to številko, in neskladje med MTU, ki ga nastavite, in MSS, na katerega omejujete, je najpogostejši način, da po popravku znova vnesete napako pisanja. Nato zaščitite vtičnico, ki nosi promet do samega strežnika VPN. Brez protect se ti paketi usmerijo nazaj v vaš lastni tunel in povezava se nikoli ne dokonča, kar je videti kot zataknjeno branje, a je zanka usmerjanja.

Soglasja ni mogoče obiti. Storitev, zagnana brez tega, da prepare vrne null, ne dobi vmesnika, in establish vrne null namesto da vrže izjemo, zato pred zagonom zanke preverite opisnik. Referenca VpnService je mesto za potrditev pogodbe builder, namesto da kopirate primer.

Preverite eno smer naenkrat

Preden se dotaknete TCP, pošljite UDP odmev skozi tunel in opazujte dolžine paketov. Nato odprite rokovanje in potrdite, da segmenti ostanejo pod MSS, ki ste ga izračunali. Štejte pakete, ne povezav, da se zastoj pokaže kot vrzel v števcu namesto kot obešena vtičnica. Če se branja po nizu pisanj ustavijo, je sumljivo okno; če pisanja spodletijo takoj, je dolžina.

Nato znova zaženite napravo in enkrat ponovite, ker je VpnService, ki deluje le do prve spremembe omrežja, težava usmerjanja in ne nadzora pretoka.

Sorodni članki