Zlyhanie client-connect v OpenVPN: je upratovanie pri disconnect zaručené?
Odmietnutý klient nevráti pravidlo firewallu ani zapísaný záznam. Porovnajte zmluvu spätného volania s vrátením zmien, ktoré musí váš hook urobiť sám.
Keď skript client-connect skončí s nenulovým kódom, OpenVPN klienta odmietne a správcovia zvyčajne predpokladajú, že zodpovedajúci skript client-disconnect všetko uprace. Často sa vôbec nespustí, pretože spracovanie disconnect závisí od toho, čo sa fáze connect podarilo dokončiť. Považovať odmietnutie a vrátenie zmien za jeden mechanizmus je to, čo z neúspešného prihlásenia robí uniknuté pravidlo firewallu alebo osirelý záznam. Sú to dve oddelené povinnosti a len jedna z nich je automatická. Prečítajte si vlastnú výstupnú cestu hooku, než začnete obviňovať server, že po sebe nechal stav.
Nenulový výstup klienta odmietne; vašu prácu nevráti
Výstupný stav client-connect je rozhodnutie o prijatí. Nula znamená prijať, čokoľvek iné znamená zbúrať inštanciu skôr, než sa plne ustanoví. Nič v tejto zmluve neskúma, čo skript už urobil vo vonkajšom svete. Ak skript pridal pravidlo iptables, zapísal riadok alebo zvýšil počítadlo, tieto zmeny odmietnutie prežijú.
Rovnaká asymetria platí pre zásuvné moduly, kde sa pre jednu inštanciu môže spustiť niekoľko funkcií connect. Neskoršie zlyhanie spätne neruší skorší úspech a skoršia funkcia nemá ako zistiť, že sesterská funkcia zlyhala.
Odmietnutie je automatické, upratovanie nie
Manuál OpenVPN 2.6 viaže spracovanie client-disconnect na úspešné dokončenie predchádzajúceho spracovania connect. Dokumentovaná výnimka pokrýva kaskádové reťaze: ak jeden krok connect už vrátil úspech, zodpovedajúce kroky disconnect sa pri búraní inštancie napriek tomu spustia, aj keď neskorší krok connect zlyhal. Tá výnimka je úzka a závisí od počtu nakonfigurovaných spätných volaní, preto vám testovanie jedného shell skriptu nič nepovie o reťazi.
Zmapujte skutočnú konfiguráciu, než okolo nej budete navrhovať: ktorý skript, ktorý modul a v akom poradí sa spúšťajú. Tabuľka nižšie uvádza, čo po polovičnom nastavení zostane.
| What the hook did before failing | What the client sees | What stays behind |
|---|---|---|
| Created a firewall entry | A rejection, with no tunnel | A rule matching an address nobody owns |
| Wrote a state row | A rejection, with no tunnel | A record of a session that never started |
| Allocated a tunnel address | A rejection, with no tunnel | An address marked busy until something releases it |
Každý riadok končí rovnako pre klienta a inak pre hostiteľa. Klient nemôže zistiť, ktorý z nich nastal, takže hook musí pred vrátením stavu zlyhania odvinúť, čo urobil.
Kompenzujte vnútri skriptu, ktorý zlyhal
Overte všetko, čo môžete, než sa dotknete zdieľaného stavu: polia certifikátu, dostupnosť adresy, skupinu, do ktorej klient patrí. Najlacnejšie odmietnutie je to, ktoré nastane pred akýmkoľvek pridelením. Keď nastavenie zahŕňa niekoľko vonkajších operácií, veďte záznam o tom, ktoré sa dokončili, a pred vrátením stavu zlyhania ich odviňte v opačnom poradí.
Konkrétny prípad: skript vytvorí záznam firewallu pre každého klienta a potom zlyhá pri zápise riadku stavu, ktorý ho opisuje. Zlyhávajúca vetva má práve vytvorený záznam odstrániť a potom skončiť s nenulovým kódom. Čakanie na udalosť disconnect, ktorá nemusí byť nikdy naplánovaná, je spôsob, akým pravidlo prežije reláciu, pre ktorú bolo určené.
Urobte kompenzáciu idempotentnou a s vlastníkom
Upratovanie musí byť bezpečné pri dvojnásobnom spustení a presné v tom, čo smie vymazať. Neskorá udalosť z predchádzajúceho pokusu nesmie odstrániť pridelenie novšej relácie len preto, že obe zdieľajú spoločné meno alebo recyklovanú adresu tunela. Zaznamenajte konkrétny handle alebo identifikátor operácie spolu so zdrojom a mažte podľa tohto kľúča, nie podľa mena. Databázové transakcie pomáhajú len s vlastnými zmenami databázy; pravidlo firewallu mimo tejto hranice potrebuje výslovný kompenzačný krok.
Predpokladajte, že proces môže zomrieť medzi zmenou a upratovaním, a pridajte zosúlaďovač, ktorý podľa plánu porovnáva vonkajší stav so zoznamom prijatých klientov.
Otestujte tri cesty, ktoré sa naozaj líšia
Precvičte tri prípady: odmietnutie pred akýmkoľvek pridelením, odmietnutie po čiastočnom pridelení a normálnu prijatú reláciu, ktorá sa neskôr skončí. Tieto tri dávajú rôzne riadky protokolu a rôzne zvyšky. Overujte vonkajší stav po každom z nich, nielen správu o zlyhaní klienta, pretože zlyhanie klienta je očakávaným výsledkom v dvoch z troch.
Zaznamenávajte fázu hooku, výstupný stav a to, čo bolo pridelené alebo uvoľnené, bez prihlasovacích údajov. Protokol hooku, ktorý pomenuje vytvorený zdroj, je to, čo robí uniknuté pravidlo dohľadateľným o šesť mesiacov.