OpenVPN client-connect-feil: er opprydding ved disconnect garantert?
En avvist klient ruller ikke tilbake en brannmurregel eller en skrevet post. Sammenlign callback-kontrakten med tilbakerullingen hooken din selv må utføre.
Når et client-connect-skript avslutter med en kode som ikke er null, avviser OpenVPN klienten, og driftsansvarlige antar vanligvis at det tilhørende client-disconnect-skriptet rydder opp. Ofte kjører det aldri, fordi disconnect-behandlingen avhenger av hva connect-fasen rakk å fullføre. Å behandle avvisning og tilbakerulling som én mekanisme er det som gjør en mislykket innlogging til en lekket brannmurregel eller en foreldreløs post. Det er to separate forpliktelser, og bare én av dem er automatisk. Les hookens egen utgangssti før du klandrer serveren for å etterlate tilstand.
En utgang som ikke er null avviser klienten; den ruller ikke tilbake arbeidet ditt
Utgangsstatusen for client-connect er en adgangsbeslutning. Null betyr å slippe inn, alt annet betyr å rive instansen ned før den er fullt etablert. Ingenting i den kontrakten undersøker hva skriptet allerede har gjort mot omverdenen. Hvis skriptet la til en iptables-regel, skrev en rad eller økte en teller, overlever disse endringene avvisningen.
Den samme asymmetrien gjelder for plugins, der flere connect-funksjoner kan kjøre for én instans. En senere feil annullerer ikke en tidligere suksess med tilbakevirkende kraft, og den tidligere funksjonen har ingen måte å få vite at en søskenfunksjon feilet.
Avvisning er automatisk, opprydding er det ikke
OpenVPN 2.6-håndboken knytter behandlingen av client-disconnect til at den forrige connect-behandlingen lyktes. Et dokumentert unntak dekker kaskadede kjeder: hvis ett connect-trinn allerede har returnert suksess, kjører de tilhørende disconnect-trinnene likevel når instansen rives ned, selv om et senere connect-trinn feilet. Unntaket er smalt og avhenger av hvor mange callbacks som er konfigurert, og derfor sier testing av ett shell-skript deg ingenting om en kjede.
Kartlegg den faktiske konfigurasjonen før du designer rundt den: hvilket skript, hvilken plugin og i hvilken rekkefølge de kjører. Tabellen nedenfor viser hva et halvferdig oppsett etterlater.
| 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 |
Hver rad ender likt for klienten og ulikt for verten. Klienten kan ikke se hvilken av dem som skjedde, så hooken må rulle tilbake det den gjorde før den returnerer feilstatusen.
Kompensér inne i skriptet som feilet
Valider alt du kan før du berører delt tilstand: sertifikatfelt, adressens tilgjengelighet, gruppen klienten tilhører. Den billigste avvisningen er den som skjer før noen tildeling. Når oppsettet spenner over flere eksterne operasjoner, før oversikt over hvilke som ble fullført, og rull dem tilbake i omvendt rekkefølge før du returnerer feilstatusen.
Et konkret tilfelle: skriptet oppretter en brannmurspost per klient og feiler deretter med å skrive tilstandsraden som beskriver den. Den feilende grenen bør fjerne posten den nettopp opprettet og deretter avslutte med en kode som ikke er null. Å vente på en disconnect-hendelse som kanskje aldri blir planlagt, er hvordan en regel overlever økten den var ment for.
Gjør kompensasjonen idempotent og eid
Opprydding må være trygg å kjøre to ganger og presis på hva den kan slette. En sen hendelse fra et tidligere forsøk bør ikke fjerne en nyere økts tildeling bare fordi begge deler et felles navn eller en gjenbrukt tunneladresse. Registrer det konkrete håndtaket eller operasjons-ID-en sammen med ressursen, og slett etter den nøkkelen i stedet for etter navn. Databasetransaksjoner hjelper bare med databasens egne endringer; en brannmurregel utenfor den grensen trenger et eksplisitt kompensasjonstrinn.
Anta at prosessen kan dø mellom endringen og oppryddingen, og legg til en avstemmer som etter en plan sammenligner ekstern tilstand med listen over godkjente klienter.
Test de tre stiene som faktisk er forskjellige
Øv på tre tilfeller: en avvisning før noe som helst er tildelt, en etter en delvis tildeling, og en normal godkjent økt som senere avsluttes. De tre gir ulike logglinjer og ulike rester. Verifiser ekstern tilstand etter hver av dem, ikke bare klientens feilmelding, fordi klientens feil er det forventede resultatet i to av de tre.
Logg hookens fase, utgangsstatusen og hva som ble tildelt eller frigitt, uten påloggingsdetaljer. En hook-logg som navngir ressursen den opprettet, er det som gjør en lekket regel finnbar seks måneder senere.