Kada skripta client-connect završi s nenultim kodom, OpenVPN odbija klijenta, a administratori obično pretpostavljaju da će odgovarajuća skripta client-disconnect počistiti. Često se nikad ne pokrene, jer obrada disconnect ovisi o tome što je connect faza uspjela dovršiti. Tretiranje odbijanja i vraćanja unazad kao jednog mehanizma pretvara neuspješnu prijavu u procurjelo firewall pravilo ili zapis bez vlasnika. To su dvije odvojene obaveze, a samo je jedna automatska. Pročitajte vlastiti izlazni put hooka prije nego što okrivite server da je ostavio stanje za sobom.

Nenulti izlaz odbija klijenta; ne poništava vaš rad

Izlazni status client-connect je odluka o prijemu. Nula znači prihvatiti, sve ostalo znači rušenje instance prije nego što je potpuno uspostavljena. Ništa u tom ugovoru ne provjerava što je skripta već učinila vanjskom svijetu. Ako je skripta dodala iptables pravilo, zapisala red ili povećala brojač, te promjene nadživljavaju odbijanje.

Ista asimetrija vrijedi za dodatke, gdje se za jednu instancu može izvršiti nekoliko connect funkcija. Kasniji neuspjeh ne poništava retroaktivno raniji uspjeh, a ranija funkcija ne može saznati da je srodna funkcija podbacila.

Odbijanje je automatsko, čišćenje nije

Priručnik OpenVPN 2.6 veže obradu client-disconnect uz uspješno dovršenu prethodnu obradu connect. Dokumentirani izuzetak pokriva kaskadne lance: ako je jedan connect korak već vratio uspjeh, odgovarajući disconnect koraci se ipak izvršavaju pri rušenju instance, iako je kasniji connect korak podbacio. Taj izuzetak je uzak i zavisi od broja konfiguriranih povratnih poziva, zato vam testiranje jedne shell skripte ne govori ništa o lancu.

Mapirajte stvarnu konfiguraciju prije nego što dizajnirate oko nje: koja skripta, koji dodatak i kojim redoslijedom se izvršavaju. Tablica ispod navodi što polovično dovršeno postavljanje ostavlja za sobom.

What the hook did before failingWhat the client seesWhat stays behind
Created a firewall entryA rejection, with no tunnelA rule matching an address nobody owns
Wrote a state rowA rejection, with no tunnelA record of a session that never started
Allocated a tunnel addressA rejection, with no tunnelAn address marked busy until something releases it

Svaki red završava isto za klijenta, a drugačije za host. Klijent ne može reći koji se od njih dogodio, pa hook mora poništiti ono što je učinio prije nego što vrati status neuspjeha.

Nadoknadite unutar skripte koja je podbacila

Provjerite sve što možete prije nego što dotaknete dijeljeno stanje: polja certifikata, dostupnost adrese, grupu kojoj klijent pripada. Najjeftinije odbijanje je ono koje se dogodi prije bilo kakve dodjele. Kada postavljanje obuhvati nekoliko vanjskih operacija, vodite evidenciju koje su dovršene i poništite ih obrnutim redoslijedom prije vraćanja statusa neuspjeha.

Konkretan slučaj: skripta stvara firewall unos za svakog klijenta, a zatim ne uspije zapisati red stanja koji ga opisuje. Grana koja podbaci treba ukloniti unos koji je upravo stvorila i zatim izaći s nenultim kodom. Čekanje na disconnect događaj koji možda nikad neće biti zakazan jeste način da pravilo nadživi sesiju kojoj je bilo namijenjeno.

Učinite nadoknadu idempotentnom i s vlasnikom

Čišćenje mora biti sigurno za dvostruko pokretanje i precizno u pogledu toga što smije izbrisati. Kasni događaj iz ranijeg pokušaja ne smije ukloniti dodjelu novije sesije samo zato što obje dijele zajedničko ime ili recikliranu adresu tunela. Zabilježite konkretni ručku ili identifikator operacije uz resurs i brišite po tom ključu, a ne po imenu. Transakcije baze podataka pomažu samo s vlastitim promjenama baze; firewall pravilo izvan te granice zahtijeva izričit korak nadoknade.

Pretpostavite da proces može umrijeti između promjene i čišćenja i dodajte usklađivač koji po rasporedu poredi vanjsko stanje s popisom prihvaćenih klijenata.

Testirajte tri puta koji se stvarno razlikuju

Vježbajte tri slučaja: odbijanje prije bilo kakve dodjele, odbijanje nakon djelimične dodjele i normalnu prihvaćenu sesiju koja kasnije završi. Ta tri daju različite linije dnevnika i različite ostatke. Provjerite vanjsko stanje nakon svakog, ne samo poruku o neuspjehu klijenta, jer je neuspjeh klijenta očekivani ishod u dva od tri slučaja.

Bilježite fazu hooka, izlazni status i što je dodijeljeno ili oslobođeno, bez vjerodajnica. Dnevnik hooka koji imenuje resurs koji je stvorio jeste ono što procurjelo pravilo čini pronalazivim šest mjeseci kasnije.

Povezani članci