Kan et OpenVPN-krokskript bruke tunnelen det nettopp bygde?
OpenVPN kjører kroker inne i sin egen oppstart, så et skript som trenger tunnelen venter på en tunnel som venter på det. Koble arbeidet fra og velg kroken etter hendelse.
Om et krokskript når den andre siden av tunnelen, avhenger av tre vilkår: hvilken hendelse det er knyttet til, om OpenVPN fortsatt er inne i oppstartssekvensen når skriptet kjører, og om arbeidet er løsrevet fra den sekvensen. De fleste skript feiler på det tredje. Å legge til en pause behandler et livssyklusproblem som et timingproblem, og det virker akkurat ofte nok til å villede.
Bestem først hendelsen, deretter mekanismen for å utsette arbeid, deretter stedet der det utsatte arbeidet kjører. De tre beslutningene er uavhengige, og å blande dem er hvordan en krok på to linjer blir en hel ettermiddag.
Hvorfor kroken venter på en tunnel som venter på den
OpenVPN kaller krokene sine synkront, inne i den samme prosessen som flytter pakker. up utløses når tun- eller tap-enheten finnes, men før noen rute legges til, og route-up utløses etter rutene; ingen av øyeblikkene lover at en motpart svarer. Mens et skript fra en av krokene fortsatt kjører, videresender ikke daemonen, så en kommando som forventer at trafikk krysser tunnelen, venter på en tunnel som venter på kommandoen. Den sirkulære ventingen er grunnen til at en manuell kjøring går gjennom og kroken får tidsavbrudd.
Den åpenbare lappen, å sove noen sekunder, virker noen ganger fordi den fjerne enden kom opp av seg selv, ikke fordi pausen reparerte noe. En hjelper som spør om beredskap er et annet svar: kroken returnerer, videresendingen starter, og hjelperen får det den trenger når det faktisk er der.
Velg kroken etter hendelse, ikke etter bekvemmelighet
Knytt up til arbeid som bare trenger enheten, route-up til arbeid som trenger ruter, og hold client-connect og client-disconnect til oppgaver per klient på serversiden. Opprydding ved frakobling må tåle å kjøre to ganger, fordi gjenoppkoblinger over et vedvarende grensesnitt ikke følger samme sekvens som en full omstart. På serveren utløses client-connect når en klient autentiserer seg, ikke når daemonen starter, noe som er verdt å bekrefte før logikk flyttes dit. Hvis arbeidet hører til tjenestens livssyklus og ikke til én tilkobling, er en systemd-enhet et bedre hjem enn noen krok.
Krokkommandoer kjøres direkte av daemonen, uten et skall imellom, så ifconfig_remote på en up-linje kommer som bokstavelig tekst. Pakk kommandoen inn i et eksplisitt skall, eller hold logikken i et skript som leser miljøet. ipchange er en direktiv som legger til egne argumenter: den gir adressen og porten til kommandoen, så et skript skrevet for ingen ser to uventede.
Tre måter å løsrive arbeidet på
Det første alternativet er å sette hjelperen i bakgrunnen fra kroken: start den med setsid eller systemd-run --scope, lukk de arvede deskriptorene og avslutt med null med en gang. Det andre er å la kroken skrive en liten tilstandsfil og la en systemd-timer eller en path-enhet handle på den, noe som holder kroken triviell og legger gjenforsøkspolitikken der det finnes logger. Det tredje er å droppe kroken helt og flytte arbeidet til en enhet som er ordnet etter VPN-tjenesten, som er det riktige svaret når arbeidet slett ikke er per tilkobling. Alle tre deler én regel: kroken må returnere før den trenger tunnelen.
Uansett hva du velger, gjør hjelperen idempotent og observerbar. To overlappende kall bør ikke utføre den samme ugjenkallelige handlingen to ganger, og en hjelper som feiler, må etterlate noe et menneske kan lese.
Skill sandkassefeil fra livssyklusfeil
Når et skript kjører fra en root-ledetekst og feiler som tjeneste, er årsaken vanligvis en sandkasse og ikke nettverket. En restriktiv ProtectHome, en skrivebeskyttet ProtectSystem eller en arbeidskatalog som ikke finnes kan gjøre skriptet eller dataene utilgjengelige, og på en SELinux-vert trenger filen også en kontekst som tillater kjøring. Les enheten med systemctl cat openvpn-server@server og journalen med journalctl -u openvpn-server@server -n 80, og se deretter etter en tillatelses- eller kontekstfeil i stedet for en tilkoblingstimeout. Å deaktivere sandkassen bør være det siste trekket, ikke det første.
En livssyklusfeil ser annerledes ut: kroken starter, hjelperen kjører, og sockelen er bare ikke der ennå. Skriv en tidsstemplet linje fra kroken selv, koble fra og til igjen, og les hendelsene i rekkefølge. Når hjelperen virkelig trenger tunnelen, la den spørre om beredskap i stedet for å sove en fast periode.
Tre felt gjør den neste rapporten nyttig: hvilken krok som kjørte, hvilken konto den brukte, og hvor den stoppet. Uten dem starter enhver senere undersøkelse på nytt.