Proč VPN hook firewallu přidává stejné pravidlo dvakrát
Opětovné připojení může váš hook spustit znovu, proto navrhujte pro požadovaný stav: vlastní řetězce, test před vložením, jednu serializovanou změnu a úzké odstranění.
Hook funguje napoprvé a po třech opětovných připojeních drží řetězec tři kopie téhož pravidla. Nic nepropadlo hlasitě; skript prostě při každém spuštění udělal, co mu bylo řečeno. VPN hook je konfigurační operace, která může běžet více než jednou, proto potřebuje vlastníka, požadovaný stav a serializovanou změnu. Jděte v tomto pořadí a duplikáty přestanou.
Dejte pravidlům vlastníka, než nějaké napíšete
Rozhodněte, který řetězec nebo tabulku tato integrace vlastní, než napíšete jediné pravidlo. Vyhrazený řetězec, který hook vytváří a vyprazdňuje, je nejjasnější forma vlastnictví, protože úklid pak může tento řetězec odstranit, aniž by se dotkl cizí politiky. Pokud musíte přidávat pravidla do sdíleného řetězce, označte je komentářem, aby pozdější hledání našlo právě ta vaše. Vlastnictví dělá odstranění bezpečným a odstranění je ta část, která tiše selhává.
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
Komentář tu není dekorace. Je to rozdíl mezi odstraněním vašeho pravidla a odstraněním pravidla, které náhodou vypadá podobně, a přežívá v uložené sadě pravidel. Napište komentář jednou do proměnné a používejte stejný řetězec v každém příkazu, který přidává, testuje nebo maže.
Testujte požadovaný stav místo opětovného přidávání
Zapište, co má existovat, dokud je tunel nahoře: která rozhraní, který zdroj a cíl, který protokol a který port. Pak vyjádřete každé pravidlo jako test následovaný vložením, aby druhé spuštění pravidlo našlo a nic neudělalo. Kontrolní příkaz skončí nulou, když pravidlo existuje, a to je přesně signál, který skript potřebuje. Reference iptables dokumentuje zde použité formy kontroly, přidání a vložení.
iptables -C VPN_HOOK -i tun0 -p tcp --dport 443 -j ACCEPT ||
iptables -A VPN_HOOK -i tun0 -p tcp --dport 443 -j ACCEPT
Pozor na pozici. Zkontrolovat pravidlo a vložit ho na začátek může posunout povolení před záměrné odmítnutí, které dřív přicházelo první, takže druhé spuštění změní chování, i když nic nepřidá. Přidávejte na konec uvnitř vlastního řetězce a pořadí ovládejte místem skoku do tohoto řetězce. Pokud na pořadí uvnitř řetězce záleží, sestavte řetězec znovu ze známého seznamu, místo abyste ho záplatovali pravidlo po pravidle.
Zastavte se, pokud potřebné pravidlo nelze vyjádřit jako stabilní test. To obvykle znamená, že požadovaný stav je stále nejasný.
Serializujte změnu místo naděje, že vydrží
Dvě volání hooku se mohou překrývat a obě mohou vidět chybějící pravidlo, než ho jedno z nich přidá. Volba čekání v xtables přiměje příkaz čekat na zámek, ale neudělá sled kontroly a přidání atomickým přes dva příkazy. Serializujte celou operaci vlastním zámkem, nebo použijte správce, který aplikuje deklarovanou dávku jako jednu transakci. nftables umí to druhé, což je jeden z důvodů, proč ho upřednostnit na hostitelích, kde je dostupný.
flock /run/vpn-hook.lock /usr/local/sbin/vpn-firewall-apply
nft -f /etc/nftables/vpn-hook.nft
Ať zvolíte jakýkoli mechanismus, držte kritickou sekci krátkou a udělejte ji znovu vstupní: hook, který selže v polovině, musí být bezpečné znovu spustit. Zaznamenejte výsledek, aby bylo opakované spuštění vidět v journalu, místo aby se odvozovalo z počtu pravidel. Pokud mohou hook volat dva různí supervizoři, opravte to nejdřív; žádný zámek nespraví dva vlastníky.
Odstraňujte jen to, co vlastníte
Odstranění musí rozeznat náhradní spojení od toho, které vyřadilo, a musí přežít událost, která nikdy nedostane řádný úklid. Mažte podle stejných identifikátorů, které jste použili k přidání, a nikdy nevyprazdňujte sdílený řetězec, abyste úklid zjednodušili. Po tvrdém zastavení spusťte při příštím startu průchod sladění, místo abyste předpokládali, že down hook proběhl.
iptables -D VPN_HOOK -i tun0 -p tcp --dport 443 -j ACCEPT
iptables -F VPN_HOOK
ip -brief link show type tun
Životnost rozhraní patří také do návrhu. Opětovné připojení může vytvořit zařízení s jiným názvem, takže pravidlo, které natvrdo kóduje název druhého tunelu, zastará, i když stále vypadá platně. Upřednostněte identitu, kterou odhaluje samo spojení, a při každém spuštění ji znovu přečtěte. Otestujte tři události odděleně: opakované připojení, náhradní připojení a vypnutí. Povolený provoz má přežít všechny tři bez duplikátů a nesouvisející služby mají zůstat nedotčené.
Průchod končí, když hook má vlastníka, test pro každé pravidlo, které přidá, jednu serializovanou cestu a odstranění, které odstraňuje jen jeho vlastní stav. Hook, který je bezpečný spustit dvakrát, má větší cenu než hook, který je jednou chytrý.