Hookul funcționează prima dată, iar după trei reconectări lanțul conține trei copii ale aceleiași reguli. Nimic nu a eșuat zgomotos; scriptul pur și simplu a făcut ce i s-a spus la fiecare rulare. Un hook VPN este o operațiune de configurare care poate rula de mai multe ori, așa că are nevoie de un proprietar, o stare dorită și o modificare serializată. Urmează această ordine și duplicatele se opresc.

Dă un proprietar regulilor înainte de a scrie vreuna

Decide ce lanț sau tabel deține această integrare înainte de a scrie o singură regulă. Un lanț dedicat pe care hookul îl creează și îl golește este cea mai clară formă de proprietate, deoarece curățarea poate apoi să elimine acel lanț fără a atinge politica altcuiva. Dacă trebuie să adaugi reguli într-un lanț partajat, marchează-le cu un comentariu pentru ca o căutare ulterioară să le găsească exact pe ale tale. Proprietatea face demontarea sigură, iar demontarea este partea care eșuează în tăcere.

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

Un comentariu nu este decor aici. Este diferența dintre a elimina regula ta și a elimina o regulă care se întâmplă să arate similar, și supraviețuiește în setul de reguli salvat. Scrie comentariul o dată într-o variabilă și folosește același șir în fiecare comandă care adaugă, testează sau șterge.

Testează starea dorită în loc să adaugi din nou

Scrie ce trebuie să existe cât timp tunelul este sus: ce interfețe, ce sursă și destinație, ce protocol și ce port. Apoi exprimă fiecare regulă ca un test urmat de o inserare, astfel încât o a doua rulare să găsească regula și să nu facă nimic. Comanda de verificare se termină cu zero când regula există, și exact acesta este semnalul de care are nevoie scriptul. Referința iptables documentează formele de verificare, adăugare și inserare folosite aici.

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

Fii atent la poziție. Verificarea unei reguli și inserarea ei la început poate mută o permisiune înaintea unei refuzări intenționate care venea prima, așa că a doua rulare schimbă comportamentul chiar dacă nu adaugă nimic. Adaugă la sfârșit în interiorul lanțului tău și controlează ordinea prin locul unde stă saltul către acel lanț. Dacă ordinea din interiorul lanțului contează, reconstruiește lanțul dintr-o listă cunoscută în loc să-l peticesti regulă cu regulă.

Oprește-te dacă regula de care ai nevoie nu poate fi exprimată ca un test stabil. Asta înseamnă de obicei că starea dorită este încă vagă.

Serializează modificarea în loc să speri că rezistă

Două invocări ale hookului se pot suprapune, iar ambele pot vedea o regulă absentă înainte ca vreuna să o adauge. Opțiunea de așteptare a xtables face o comandă să aștepte blocajul, dar nu face atomică o secvență verifică-și-adaugă între două comenzi. Serializează întreaga operațiune cu propriul blocaj sau folosește un manager care aplică un lot declarat ca o singură tranzacție. nftables poate face ultima variantă, ceea ce este un motiv să-l preferi pe gazdele unde este disponibil.

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

Indiferent de mecanismul ales, ține secțiunea critică scurtă și fă-o reentrantă: un hook care eșuează la jumătate ar trebui să fie sigur de rulat din nou. Înregistrează rezultatul pentru ca o rulare repetată să fie vizibilă în jurnal în loc să fie dedusă din numărul de reguli. Dacă doi supervizori diferiți pot invoca hookul, repară asta mai întâi; niciun blocaj nu repară doi proprietari.

Demolează doar ce este al tău

Demontarea trebuie să distingă o conexiune de înlocuire de cea pe care a pensionat-o și trebuie să supraviețuiască unui eveniment care nu primește niciodată o curățare ordonată. Șterge după aceiași identificatori pe care i-ai folosit la adăugare, și nu goli niciodată un lanț partajat pentru a simplifica curățarea. După o oprire dură, rulează o trecere de reconciliere la următoarea pornire în loc să presupui că hookul de coborâre a rulat.

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

Durata de viață a interfeței face parte și ea din proiect. O reconectare poate crea un dispozitiv cu alt nume, așa că o regulă care codifică fix numele celui de-al doilea tunel devine învechită în timp ce încă pare validă. Preferă identitatea pe care o expune conexiunea însăși și recitește-o la fiecare rulare. Testează cele trei evenimente separat: o conexiune repetată, o conexiune de înlocuire și o oprire. Traficul permis ar trebui să supraviețuiască tuturor trei fără duplicate, iar serviciile nelegate ar trebui să rămână neatinse.

Plimbarea se termină când hookul are un proprietar, un test pentru fiecare regulă pe care o adaugă, o singură cale serializată și o demontare care elimină doar propria stare. Un hook care este sigur de rulat de două ori valorează mai mult decât un hook care este deștept o dată.

Articole similare