OpenVPN client-connect-fout: is opruimen bij disconnect gegarandeerd?
Een geweigerde client draait geen firewallregel of geschreven record terug. Vergelijk het callback-contract met de terugdraai die je hook zelf moet uitvoeren.
Wanneer een client-connect-script met een code ongelijk nul eindigt, weigert OpenVPN de client, en beheerders gaan er meestal van uit dat het bijbehorende client-disconnect-script opruimt. Vaak draait dat nooit, omdat de disconnect-verwerking afhangt van wat de connect-fase wist af te ronden. Weigering en terugdraai als één mechanisme behandelen is wat een mislukte login verandert in een gelekte firewallregel of een verweesd record. Het zijn twee aparte verplichtingen, en slechts één ervan is automatisch. Lees het eigen exitpad van de hook voordat je de server verwijt staat achter te laten.
Een exit ongelijk nul weigert de client; hij draait je werk niet terug
De exitstatus van client-connect is een toelatingsbeslissing. Nul betekent toelaten, al het andere betekent de instantie afbreken voordat hij volledig is opgebouwd. Niets in dat contract onderzoekt wat het script al met de buitenwereld heeft gedaan. Als het script een iptables-regel toevoegde, een rij schreef of een teller verhoogde, overleven die wijzigingen de weigering.
Dezelfde asymmetrie geldt voor plugins, waar meerdere connect-functies voor één instantie kunnen draaien. Een latere fout annuleert een eerdere succes niet met terugwerkende kracht, en de eerdere functie heeft geen manier om te weten dat een zusterfunctie faalde.
Weigering is automatisch, opruimen niet
De OpenVPN 2.6-handleiding koppelt de client-disconnect-verwerking aan het slagen van de eerdere connect-verwerking. Een gedocumenteerde uitzondering dekt cascadketens: als één connect-stap al succes heeft teruggegeven, draaien de bijbehorende disconnect-stappen toch wanneer de instantie wordt afgebroken, ook al faalde een latere connect-stap. Die uitzondering is smal en hangt af van hoeveel callbacks er zijn geconfigureerd, daarom zegt het testen van één shellscript niets over een keten.
Breng de werkelijke configuratie in kaart voordat je eromheen ontwerpt: welk script, welke plugin en in welke volgorde ze draaien. De tabel hieronder somt op wat een half afgemaakte opzet achterlaat.
| 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 |
Elke rij eindigt hetzelfde voor de client en anders voor de host. De client kan niet zien welke van beide is gebeurd, dus moet de hook terugdraaien wat hij deed voordat hij de foutstatus teruggeeft.
Compenseer in het script dat faalde
Valideer alles wat je kunt voordat je gedeelde staat aanraakt: certificaatvelden, beschikbaarheid van het adres, de groep waartoe de client behoort. De goedkoopste weigering is degene die vóór enige toewijzing plaatsvindt. Zodra de opzet meerdere externe bewerkingen omvat, houd bij welke zijn voltooid en draai ze in omgekeerde volgorde terug voordat je de foutstatus teruggeeft.
Een concreet geval: het script maakt een firewallvermelding per client en faalt er dan in de statusregel te schrijven die die vermelding beschrijft. De falende tak moet de zojuist gemaakte vermelding verwijderen en daarna met een code ongelijk nul eindigen. Wachten op een disconnect-gebeurtenis die misschien nooit wordt ingepland, is hoe een regel de sessie overleeft waarvoor hij bedoeld was.
Maak de compensatie idempotent en eigendom
Opruimen moet veilig twee keer te draaien zijn en precies weten wat het mag verwijderen. Een late gebeurtenis van een eerdere poging mag niet de toewijzing van een nieuwere sessie verwijderen, alleen omdat beide een gemeenschappelijke naam of een hergebruikt tunneladres delen. Leg de specifieke handle of het bewerkings-ID vast bij de resource, en verwijder op die sleutel in plaats van op naam. Databasetransacties helpen alleen bij de eigen wijzigingen van de database; een firewallregel buiten die grens heeft een expliciete compensatiestap nodig.
Ga ervan uit dat het proces kan sterven tussen de wijziging en het opruimen, en voeg een afstemmer toe die volgens een schema de externe staat vergelijkt met de lijst toegelaten clients.
Test de drie paden die echt verschillen
Oefen drie gevallen: een weigering voordat er iets is toegewezen, een na een gedeeltelijke toewijzing, en een normale toegelaten sessie die later eindigt. Die drie leveren verschillende logregels en verschillende resten op. Controleer de externe staat na elk daarvan, niet alleen de foutmelding van de client, want het falen van de client is in twee van de drie het verwachte resultaat.
Log de hookfase, de exitstatus en wat er is toegewezen of vrijgegeven, zonder inloggegevens. Een hooklog die de resource noemt die hij aanmaakte, is wat een gelekte regel zes maanden later vindbaar maakt.