Kan eit OpenVPN-krokeskript bruke tunnelen det nettopp bygde?
OpenVPN køyrer krokar inne i sin eigen oppstart, så eit skript som treng tunnelen, ventar på ein tunnel som ventar på det. Kople arbeidet frå og vel kroken etter hending.
Om eit krokeskript når den andre sida av tunnelen, kjem an på tre vilkår: kva hending det er knytt til, om OpenVPN framleis er inne i oppstartssekvensen når skriptet køyrer, og om arbeidet er løyst frå den sekvensen. Dei fleste skript feilar på det tredje. Å leggje til ein pause handsamar eit livssyklusproblem som eit timingproblem, og det verkar akkurat ofte nok til å villeie.
Avgjer først hendinga, deretter mekanismen for å utsetje arbeid, deretter staden der det utsette arbeidet køyrer. Dei tre avgjerdene er uavhengige, og å blande dei er korleis ein krok på to linjer blir ein heil ettermiddag.
Kvifor kroken ventar på ein tunnel som ventar på han
OpenVPN kallar krokane sine synkront, inne i den same prosessen som flyttar pakkar. up blir utløyst når tun- eller tap-eininga finst, men før noka rute blir lagd til, og route-up blir utløyst etter rutene; ingen av augneblinkane lovar at ein motpart svarar. Medan eit skript frå ein av krokane framleis køyrer, vidaresender ikkje daemonen, så ein kommando som ventar at trafikk kryssar tunnelen, ventar på ein tunnel som ventar på kommandoen. Den sirkulære ventetida er grunnen til at ei manuell køyring går gjennom og kroken får tidsavbrot.
Den openberre lappen, å sove nokre sekund, verkar nokre gonger fordi den fjerne enden kom opp av seg sjølv, ikkje fordi pausen reparerte noko. Ein hjelpar som spør om beredskap er eit anna svar: kroken returnerer, vidaresendinga startar, og hjelparen får det han treng når det faktisk er der.
Vel kroken etter hending, ikkje etter bekvemmelegheit
Knyt up til arbeid som berre treng eininga, route-up til arbeid som treng ruter, og hald client-connect og client-disconnect til oppgåver per klient på serversida. Opprydding ved fråkopling må tole å køyre to gonger, fordi attoppkoplingar over eit varig grensesnitt ikkje følgjer same sekvens som ein full omstart. På serveren blir client-connect utløyst når ein klient autentiserer seg, ikkje når daemonen startar, noko som er verdt å stadfeste før logikk blir flytt dit. Viss arbeidet høyrer til livssyklusen til tenesta og ikkje til éi tilkopling, er ei systemd-eining eit betre heim enn nokon krok.
Krokkommandoar blir køyrde direkte av daemonen, utan eit skal imellom, så ifconfig_remote på ei up-linje kjem som bokstaveleg tekst. Pakk kommandoen inn i eit eksplisitt skal, eller hald logikken i eit skript som les miljøet. ipchange er eit direktiv som legg til eigne argument: det gir adressa og porten til kommandoen, så eit skript skrive for ingen ser to uventa.
Tre måtar å kople arbeidet frå på
Det første alternativet er å setje hjelparen i bakgrunnen frå kroken: start han med setsid eller systemd-run --scope, lukk dei arva deskriptorane og avslutt med null med ein gong. Det andre er å la kroken skrive ei lita tilstandsfil og la ein systemd-timer eller ei path-eining handle på henne, noko som held kroken triviell og legg gjenforsk-politikken der det finst loggar. Det tredje er å droppe kroken heilt og flytte arbeidet til ei eining som er ordna etter VPN-tenesta, som er det rette svaret når arbeidet slett ikkje er per tilkopling. Alle tre deler éin regel: kroken må returnere før han treng tunnelen.
Uansett kva du vel, gjer hjelparen idempotent og observerbar. To overlappande kall bør ikkje utføre den same ugjenkallelege handlinga to gonger, og ein hjelpar som feilar, må etterlate noko eit menneske kan lese.
Skil sandkassefeil frå livssyklusfeil
Når eit skript køyrer frå ein root-leietekst og feilar som teneste, er årsaka vanlegvis ein sandkasse og ikkje nettverket. Ein restriktiv ProtectHome, ein skriveverna ProtectSystem eller ein arbeidskatalog som ikkje finst kan gjere skriptet eller dataa utilgjengelege, og på ein SELinux-vert treng fila også ein kontekst som tillèt køyring. Les eininga med systemctl cat openvpn-server@server og journalen med journalctl -u openvpn-server@server -n 80, og sjå deretter etter ein løyve- eller kontekstfeil i staden for ein tilkoplingstimeout. Å deaktivere sandkassen bør vere det siste trekket, ikkje det første.
Ein livssyklusfeil ser annleis ut: kroken startar, hjelparen køyrer, og sockelen er berre ikkje der enno. Skriv ei tidsstempla linje frå kroken sjølv, kople frå og til igjen, og les hendingane i rekkjefølgje. Når hjelparen verkeleg treng tunnelen, la han spørje om beredskap i staden for å sove ein fast periode.
Tre felt gjer den neste rapporten nyttig: kva krok som køyrde, kva konto han brukte, og kvar han stoppa. Utan dei startar kvar seinare undersøking på nytt.