Twee simptome verskyn in dieselfde VpnService-lus en word aan dieselfde ding toegeskryf: 'n leser wat nooit terugkeer nie, en 'n skryf wat met ENOBUFS misluk. Hulle is nie variasies van een fout nie. 'n Lees wat vasgehaak het, is 'n meningsverskil oor vloeibeheer met die eweknie; 'n mislukte skryf is 'n pakket wat die koppelvlak nie sal aanvaar nie. Behandel hulle as een probleem en jy sal 'n dag spandeer aan die instel van buffers wat nooit betrokke was nie. Die verdeling hieronder is hoe ek besluit watter helfte van die lus ek eerste instrumenteer.

Een lus, twee onafhanklike foutpunte

Jou diens lees 'n IP-pakket uit die TUN-lêerbeskrywer, ondersoek dit en skryf 'n antwoord terug na dieselfde beskrywer. Alles wat in daardie pad breek, kom by een van daardie twee oproepe na vore, en daarom word albei as 'n stukkende tonnel gerapporteer. Die oproepe het verskillende kontrakte. 'n Lees wag dat die kern 'n pakket aan jou gee, en 'n skryf gee die kern 'n pakket wat dit mag weier.

Leses is die maklike helfte om oor te redeneer. 'n Lees wat niks teruggee nie, wag óf vir verkeer wat nooit aankom nie, óf omdat die eweknie opgehou stuur het.

'n Lees wat vasgehaak het, is 'n meningsverskil oor vloeibeheer

Om 'n TUN-toestel te lees, blokkeer totdat 'n pakket beskikbaar is. Dit is ontwerpte gedrag, en dit is waarom 'n draad wat in read parkeer op 'n ledige skakel normaal lyk. Dit word 'n hang wanneer jou eie TCP-stapel aanhou om data van die plaaslike toepassing te aanvaar maar nooit genoeg venster adverteer vir die afgeleë eweknie om meer te stuur nie. Die eweknie vul die venster wat jy geadverteer het, wag vir 'n ACK en 'n vensteropdatering, en stop. Jou leser het dan niks om terug te gee nie, en die toepassing sien 'n verbinding wat oop en stil is.

Die algemene oorsake is 'n stapel wat in die sokkie skryf sonder om die geadverteerde venster te volg, en een wat vergeet om 'n vensteropdatering te stuur nadat dit sy buffer leeggemaak het. Van buite lyk hulle identies: grepe gaan uit, niks kom terug, geen fout word opgewerp nie. Om die leser-draad op parsering, DNS-resolusie of skyf-I/O te blokkeer, lewer dieselfde vorm van simptoom vir 'n onverwante rede, so bevestig dat die draad werklik in read is voordat jy vloeibeheer blameer.

Kontroleer die eweknie se stuurwachtou en die venster wat dit laas gesien het. As die eweknie data hou omdat jou venster nul is, is die regstelling in jou ACK-pad, nie in die TUN-lees nie.

ENOBUFS is 'n grootteprobleem, nie 'n buffertekort nie

'n Skryf wat ENOBUFS op 'n TUN-koppelvlak teruggee, verwerp gewoonlik die pakketlengte. Die koppelvlak het 'n MTU, 'n pakket groter as dit kan nie in die ry geplaas word nie, en om dieselfde pakket weer te probeer misluk elke keer op dieselfde manier. Daardie determinisme is die aanduiding. 'n Werklike buffertekort verdwyn soos die druk daal, terwyl 'n grootteverwerping nie omgee hoe lank jy wag nie.

TCP het 'n meganisme presies hiervoor, en dit is die stap wat mense oorslaan: die MSS-beperking. Wanneer jy segmente in gebruikersruimte sintetiseer, kies jy die nutsladinggrootte, en om dit uit die plaaslike koppelvlak se MTU eerder as die tonnel se MTU te kies, lewer segmente wat die tonnel nie kan dra nie. Beperk tot die kleinste van die twee. Die beperking dek slegs TCP, so 'n oorgrootte UDP-datagram moet deur jou kode gefragmenteer of laat vaar word.

Teken die lengte van elke pakket aan wat jy skryf terwyl jy ontfout. Die lengte wat misluk, is die antwoord, en dit sal nie tussen pogings verander nie.

Drie metings wat die gevalle skei

Jy het nie 'n ontfouter vir enige van die twee mislukkings nodig nie. Drie waarnemings is genoeg om jouself na die regte afdeling te lei, en dit neem minder tyd as 'n herbou.

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

As die derde ry pas, is die lus self reg en sit die probleem waar die tonnel dit nie kan sien nie: 'n onbeskermde vervoersokkie wat jou eie VPN-verkeer terug in die tonnel dra, wat gewoonlik verskyn as 'n verbinding wat slaag en dan niks lewer nie.

Maak die leiding reg waarvan beide paaie afhanklik is

Geen van die simptome is die moeite werd om na te jaag voordat die koppelvlak korrek gebou is nie. Die bouer-oproepe wat saak maak, is die adres, die roete, die MTU en toestemming, in daardie volgorde:

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

Stel die MTU op die tonnel se werklike waarde eerder as om dit te laat by wat die voorbeeld gebruik het. Alles wat jy later skryf, word deur daardie getal begrens, en 'n wanverhouding tussen die MTU wat jy stel en die MSS waartoe jy beperk, is die algemeenste manier om die skryffout ná 'n regstelling terug te bring. Beskerm dan die sokkie wat verkeer na die VPN-bediener self dra. Sonder protect word daardie pakkette terug in jou eie tonnel gerouteer en die verbinding voltooi nooit, wat soos 'n vasgehaakte lees lyk maar 'n routeringslus is.

Toestemming kan nie omseil word nie. 'n Diens wat begin is sonder dat prepare null teruggee, kry geen koppelvlak nie, en establish gee null terug eerder as om 'n fout te gooi, so kontroleer die beskrywer voordat jy jou lus begin. Die VpnService-verwysing is die plek om die bouer-kontrak te bevestig eerder as om 'n voorbeeld te kopieer.

Verifieer een rigting op 'n slag

Stuur 'n UDP-eggo deur die tonnel en kyk na pakketlengtes voordat jy aan TCP raak. Maak dan 'n handdruk oop en bevestig dat die segmente onder die MSS bly wat jy bereken het. Tel pakkette eerder as verbindings, sodat 'n stagnasie as 'n gaping in die teller verskyn eerder as 'n hangende sokkie. As leses ná 'n uitbarsting van skrywes stop, is die venster die verdagte; as skrywes onmiddellik misluk, is dit die lengte.

Herbegin dan die toestel en herhaal een keer, want 'n VpnService wat net werk tot die eerste netwerkverandering is 'n routeringsprobleem eerder as 'n vloeibeheer-een.

Verwante artikels