Zapis o prekidu veze stiže nakon što je druga veza pod istim imenom već počela, a rukovalac koji ažurira najnoviji red za tog korisnika zatvara pogrešnu sesiju. Greška nije u poređenju vremenskih oznaka. Greška je u pretpostavci da ime plus cijela sekunda identifikuju jednu sesiju. Hook događaji opisuju veze, a veza treba ključ koji pripada samo njoj.

Počnite od toga šta varijable prekida zapravo znače. Tek tada izbor identifikatora ima smisla.

Šta hook za prekid zaista nosi

U Community OpenVPN 2.6 referenca za hookove time_unix definiše kao trenutak kada se klijent povezao; postavlja se prije nego što se hook za povezivanje pokrene i ne redefiniše se kada se hook za prekid kasnije aktivira. time_duration daje dužinu te sesije u sekundama, pa je kraj otprilike vrijeme povezivanja plus trajanje. Oba su cijele sekunde i nijedno nije trenutak kada je vaša baza podataka obradila događaj. Upravo razdvajanje tih tri vremena čini da korelacija opstane, umjesto da samo izgleda ispravno tokom testiranja.

Ova aritmetika zaslužuje da bude zapisana, jer je to jedino vrijeme završetka koje sam hook nudi. Kašnjenje obrade i razlike u satovima između hostova i dalje ostaju izvan nje.

Zašto očigledan par nije jedinstven

Uparivanje imena s vremenom povezivanja sužava pretragu i još uvijek ne identifikuje sesiju. Klijent se može ponovo povezati unutar iste sekunde, pa dvije sesije mogu dijeliti obje vrijednosti. Dvije instance daemona, ili zamjena servera koja zadržava istu konfiguraciju, mogu proizvesti taj par iz različitih procesa. Adrese tunela se recikliraju iz istog razloga, što ih čini atributima sesije, a ne identifikatorima za nju.

Način kvara je tih. Kasni prekid prve sesije poklapa se s najnovijim redom i završava dodjelu koju druga sesija još koristi, pa korisnik doživljava slučajan gubitak pristupa koji ničim nije izazvao. Broj redova koji nakon toga izgleda ispravno otežava uočavanje problema.

Odakle dolazi stabilan identitet

Upravljački interfejs dodjeljuje svakom klijentu identifikator klijentske instance, a taj identifikator je ograničen na instancu daemona koja ga je izdala. Upotrebljiv vanjski ključ kombinuje stabilan identifikator servera, epohu koja se mijenja kada daemon počne i taj klijentski ID. Epoha je važna jer se identifikatori ponovo pokreću s procesom, a goli ID procesa može kasnije ponovo upotrijebiti nešto nepovezano.

Varijable okruženja postavljene unutar potomkovne skripte za povezivanje ne prenose se u kasniju skriptu za prekid roditeljskog daemona, jer se te skripte izvršavaju kao odvojeni procesi sa svojim okruženjima. Zato je generisanje UUID-a u trenutku povezivanja pola rješenja. Strana prekida mora moći imenovati isti UUID, što znači da identitet mora živjeti negdje gdje mogu doći oba događaja.

Učinite završetak uslovnim i idempotentnim

Završavajte po vlasniku sesije, ne po korisniku. Rukovalac koji briše bilo koju dodjelu koja trenutno pripada nekom imenu na kraju će obrisati pogrešnu, a jedina odbrana je provjeriti da je zapis koji se uklanja zapis koji ovaj događaj opisuje.

Upravljački interfejs prihvata jedan povezani upravljački klijent u jednom trenutku, pa se integrirajte s onim ko ga već posjeduje umjesto da priključite drugog posmatrača koji se takmiči za isti socket.

Rukujte ponovljenim događajima bez dvostruke promjene ishoda i čuvajte neuparene događaje za usklađivanje umjesto da ih odbacujete. Povratni poziv prekida ima dokumentovane uslove životnog ciklusa i možda nikada neće stići nakon pada ili prisilnog zaustavljanja, pa dizajn treba način da predstavi sesiju čiji događaj završetka nedostaje.

Namjerno testirajte nezgodne slučajeve: dva ponovna povezivanja unutar jedne sekunde, dvije instance daemona, povezivanje čija je obrada neuspješna i ponovno pokretanje daemona usred sesije. Ključ koji preživi sva četiri vrijedi povjerenja.

Povezani članci