Hooken virker første gang, og etter tre nye tilkoblinger holder kjeden tre kopier av samme regel. Ingenting feilet høylytt; skriptet gjorde rett og slett det det ble bedt om hver gang det kjørte. En VPN-hook er en konfigurasjonsoperasjon som kan kjøre mer enn én gang, så den trenger en eier, en ønsket tilstand og én serialisert endring. Følg den rekkefølgen, og duplikatene stopper.

Gi reglene en eier før du skriver noen

Bestem hvilken kjede eller tabell denne integrasjonen eier før du skriver én eneste regel. En egen kjede som hooken oppretter og tømmer, er den klareste formen for eierskap, fordi oppryddingen da kan fjerne den kjeden uten å røre noen andres policy. Hvis du må legge regler til en delt kjede, merker du dem med en kommentar slik at et senere søk finner nøyaktig dine. Eierskap er det som gjør nedrivingen trygg, og nedrivingen er den delen som feiler i stillhet.

iptables -N VPN_HOOK 2>/dev/null || true
iptables -C INPUT -j VPN_HOOK 2>/dev/null || iptables -I INPUT -j VPN_HOOK
iptables -S VPN_HOOK

En kommentar er ikke utsmykning her. Den er forskjellen mellom å fjerne regelen din og å fjerne en regel som tilfeldigvis ser lik ut, og den overlever i det lagrede regelsettet. Skriv kommentaren én gang i en variabel og bruk den samme strengen i hver kommando som legger til, tester eller sletter.

Test for ønsket tilstand i stedet for å legge til på nytt

Skriv ned hva som skal finnes mens tunnelen er oppe: hvilke grensesnitt, hvilken kilde og destinasjon, hvilken protokoll og hvilken port. Uttrykk deretter hver regel som en test etterfulgt av en innsetting, slik at en andre kjøring finner regelen og ikke gjør noe. Kontrollkommandoen avslutter med null når regelen finnes, og det er nøyaktig signalet skriptet trenger. iptables-referansen dokumenterer formene for kontroll, tilføyelse og innsetting som brukes her.

iptables -C VPN_HOOK -i tun0 -p tcp --dport 443 -j ACCEPT ||
  iptables -A VPN_HOOK -i tun0 -p tcp --dport 443 -j ACCEPT

Vær forsiktig med plasseringen. Å kontrollere en regel og sette den inn øverst kan flytte en tillatelse foran en bevisst avvisning som tidligere kom først, så den andre kjøringen endrer atferd selv om den ikke legger til noe. Legg til bakerst inne i din egen kjede, og styr rekkefølgen etter hvor hoppet til den kjeden ligger. Hvis rekkefølgen inne i kjeden er viktig, bygg kjeden på nytt fra en kjent liste i stedet for å lappe den regel for regel.

Stopp hvis regelen du trenger ikke kan uttrykkes som en stabil test. Det betyr vanligvis at den ønskede tilstanden fortsatt er uklar.

Serialiser endringen i stedet for å håpe at den holder

To hook-kall kan overlappe, og begge kan se en manglende regel før en av dem legger den til. Ventevalget i xtables får en kommando til å vente på låsen, men det gjør ikke en kontroller-så-legg-til-sekvens atomisk over to kommandoer. Serialiser hele operasjonen med din egen lås, eller bruk en behandler som bruker en erklært batch som én transaksjon. nftables kan gjøre det siste, som er en grunn til å foretrekke det på verter der det er tilgjengelig.

flock /run/vpn-hook.lock /usr/local/sbin/vpn-firewall-apply
nft -f /etc/nftables/vpn-hook.nft

Uansett hvilken mekanisme du velger, hold den kritiske seksjonen kort og gjør den gjeninntrengelig: en hook som feiler halvveis, bør være trygg å kjøre på nytt. Logg resultatet slik at en gjentatt kjøring er synlig i journalen i stedet for å bli utledet fra et regelantall. Hvis to forskjellige veiledere kan kalle hooken, fiks det først; ingen lås reparerer to eiere.

Riv bare ned det du eier

Nedrivingen må skille en erstatningstilkobling fra den den pensjonerte, og den må tåle en hendelse som aldri får en ryddig opprydding. Slett etter de samme identifikatorene du brukte til å legge til, og tøm aldri en delt kjede for å gjøre oppryddingen enkel. Etter en hard stopp, kjør en avstemming ved neste start i stedet for å anta at ned-hooken kjørte.

iptables -D VPN_HOOK -i tun0 -p tcp --dport 443 -j ACCEPT
iptables -F VPN_HOOK
ip -brief link show type tun

Levetiden til grensesnittet hører også med i designet. En ny tilkobling kan opprette en enhet med et annet navn, så en regel som hardkoder navnet til den andre tunnelen, blir utdatert mens den fortsatt ser gyldig ut. Foretrekk identiteten som tilkoblingen selv avdekker, og les den på nytt ved hver kjøring. Test de tre hendelsene hver for seg: en gjentatt tilkobling, en erstatningstilkobling og en nedstenging. Den tillatte trafikken skal overleve alle tre uten duplikater, og urelaterte tjenester skal være urørt.

Gjennomgangen slutter når hooken har en eier, en test for hver regel den legger til, én serialisert vei og en nedriving som bare fjerner dens egen tilstand. En hook som er trygg å kjøre to ganger, er verdt mer enn en hook som er smart én gang.

Relaterte artikler