Kavelj deluje prvič, po treh ponovnih povezavah pa veriga vsebuje tri kopije istega pravila. Nič ni glasno spodletelo; skript je preprosto ob vsakem zagonu naredil, kar so mu rekli. Kavelj VPN je konfiguracijska operacija, ki lahko teče več kot enkrat, zato potrebuje lastnika, želeno stanje in serializirano spremembo. Pojdite v tem vrstnem redu in dvojniki se ustavijo.

Dajte pravilom lastnika, preden napišete katero koli

Odločite, katera veriga ali tabela pripada tej integraciji, preden napišete eno samo pravilo. Namenska veriga, ki jo kavelj ustvari in izprazni, je najjasnejša oblika lastništva, ker lahko čiščenje nato to verigo odstrani, ne da bi se dotaknilo politike koga drugega. Če morate pravila dodajati v skupno verigo, jih označite s komentarjem, da bo poznejše iskanje našlo natanko vaša. Lastništvo naredi razstavljanje varno, razstavljanje pa je tisti del, ki tiho spodleti.

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

Komentar tu ni okras. Je razlika med odstranitvijo vašega pravila in odstranitvijo pravila, ki je slučajno podobno, in preživi v shranjenem naboru pravil. Napišite komentar enkrat v spremenljivko in uporabite isti niz v vsakem ukazu, ki dodaja, preizkuša ali briše.

Preizkusite želeno stanje namesto ponovnega dodajanja

Zapišite, kaj mora obstajati, dokler je tunel pokonci: kateri vmesniki, kateri vir in cilj, kateri protokol in katera vrata. Nato izrazite vsako pravilo kot preizkus, ki mu sledi vstavitev, da bo drugi zagon našel pravilo in ne bo naredil ničesar. Ukaz za preverjanje se konča z ničlo, ko pravilo obstaja, in to je natanko signal, ki ga skript potrebuje. Referenca za iptables dokumentira tu uporabljene oblike preverjanja, dodajanja in vstavljanja.

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

Bodite pozorni na položaj. Preverjanje pravila in vstavitev na začetek lahko premakne dovoljenje pred namerno zavrnitvijo, ki je prej prišla prva, zato drugi zagon spremeni vedenje, čeprav ne doda ničesar. Dodajajte na koncu znotraj lastne verige in nadzorujte vrstni red po tem, kje je skok v to verigo. Če je vrstni red znotraj verige pomemben, verigo znova zgradite iz znanega seznama, namesto da bi jo krpali pravilo za pravilom.

Ustavite se, če potrebnega pravila ni mogoče izraziti kot stabilen preizkus. To običajno pomeni, da je želeno stanje še vedno nejasno.

Serializirajte spremembo namesto upanja, da bo zdržala

Dva klica kavlja se lahko prekrijeta in oba lahko vidita manjkajoče pravilo, preden ga eden doda. Možnost čakanja v xtables prisili ukaz, da čaka na zaklep, vendar ne naredi zaporedja preveri-in-dodaj atomskega čez dva ukaza. Serializirajte celotno operacijo z lastnim zaklepom ali uporabite upravitelja, ki uporabi deklarirano serijo kot eno transakcijo. nftables zmore slednje, kar je eden od razlogov, da ga imejte raje na gostiteljih, kjer je na voljo.

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

Ne glede na mehanizem, ki ga izberete, imejte kritični odsek kratek in ga naredite ponovno vhodnega: kavelj, ki spodleti na pol poti, mora biti varen za ponovni zagon. Zabeležite izid, da bo ponovljen zagon viden v dnevniku, namesto da bi ga sklepali iz števila pravil. Če lahko kavelj kličeta dva različna nadzornika, to najprej popravite; noben zaklep ne popravi dveh lastnikov.

Razstavite samo tisto, kar je vaše

Razstavljanje mora razlikovati nadomestno povezavo od tiste, ki jo je upokojilo, in mora preživeti dogodek, ki nikoli ne dobi urejenega čiščenja. Brišite po istih identifikatorjih, ki ste jih uporabili za dodajanje, in nikoli ne izpraznite skupne verige, da bi poenostavili čiščenje. Po trdem zaustavljanju pri naslednjem zagonu izvedite prehod usklajevanja, namesto da bi domnevali, da je spodnji kavelj tekel.

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

Življenjska doba vmesnika sodi tudi v načrt. Ponovna povezava lahko ustvari napravo z drugim imenom, zato pravilo, ki trdo kodira ime drugega tunela, zastara, medtem ko je še videti veljavno. Prednost dajte identiteti, ki jo razkrije sama povezava, in jo pri vsakem zagonu znova preberite. Preizkusite tri dogodke ločeno: ponovljena povezava, nadomestna povezava in izklop. Dovoljeni promet naj preživi vse tri brez dvojnikov, nepovezane storitve pa naj ostanejo nedotaknjene.

Pot se konča, ko ima kavelj lastnika, preizkus za vsako pravilo, ki ga doda, eno serializirano pot in razstavljanje, ki odstrani samo njegovo lastno stanje. Kavelj, ki ga je varno zagnati dvakrat, je vreden več kot kavelj, ki je enkrat pameten.

Sorodni članki