Защо кука на VPN защитна стена добавя същото правило два пъти
Повторно свързване може да пусне куката отново, затова проектирайте за желаното състояние: собствени вериги, тест преди вмъкване, една сериализирана промяна и тясно разглобяване.
Куката работи първия път, а след три повторни свързвания веригата държи три копия на същото правило. Нищо не се провали шумно; скриптът просто правеше това, което му се казваше при всяко изпълнение. Куката на VPN е операция по конфигурацията, която може да се изпълни повече от веднъж, затова ѝ трябва собственик, желано състояние и сериализирана промяна. Вървете в този ред и дубликатите спират.
Дайте собственик на правилата, преди да напишете каквото и да е
Решете коя верига или таблица притежава тази интеграция, преди да напишете дори едно правило. Отделна верига, която куката създава и изчиства, е най-ясната форма на собственост, защото почистването може после да премахне тази верига, без да пипа чужда политика. Ако трябва да добавяте правила към споделена верига, маркирайте ги с коментар, за да намери по-късно търсене точно вашите. Собствеността прави разглобяването безопасно, а разглобяването е частта, която се проваля тихо.
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
Коментарът тук не е украшение. Той е разликата между премахването на вашето правило и премахването на правило, което случайно изглежда подобно, и оцелява в запазения набор от правила. Напишете коментара веднъж в променлива и използвайте същия низ във всяка команда, която добавя, тества или изтрива.
Тествайте желаното състояние, вместо да добавяте отново
Запишете какво трябва да съществува, докато тунелът е вдигнат: кои интерфейси, кой източник и дестинация, кой протокол и кой порт. После изразете всяко правило като тест, последван от вмъкване, така че второ изпълнение да намери правилото и да не направи нищо. Командата за проверка излиза с нула, когато правилото съществува, и това е точно сигналът, който скриптът иска. Справката за iptables документира използваните тук форми за проверка, добавяне и вмъкване.
iptables -C VPN_HOOK -i tun0 -p tcp --dport 443 -j ACCEPT ||
iptables -A VPN_HOOK -i tun0 -p tcp --dport 443 -j ACCEPT
Внимавайте с позицията. Проверка на правило и вмъкване в началото може да премести разрешение пред умишлено отхвърляне, което преди идваше първо, така че второто изпълнение променя поведението, макар да не добавя нищо. Добавяйте в края вътре в собствената си верига и управлявайте подредбата чрез мястото на скока към тази верига. Ако редът вътре във веригата е важен, изградете веригата наново от известен списък, вместо да я кърпите правило по правило.
Спрете, ако нужното правило не може да се изрази като стабилен тест. Това обикновено означава, че желаното състояние още е неясно.
Сериализирайте промяната, вместо да се надявате, че ще се задържи
Две извиквания на куката могат да се припокрият и двете могат да видят липсващо правило, преди някое от тях да го добави. Опцията за изчакване на xtables кара командата да чака ключалката, но не прави последователността „проверка, после добавяне“ атомарна между две команди. Сериализирайте цялата операция със своя собствена ключалка или използвайте мениджър, който прилага деклариран пакет като една транзакция. nftables може да направи последното и това е една от причините да го предпочитате на хостове, където е наличен.
flock /run/vpn-hook.lock /usr/local/sbin/vpn-firewall-apply
nft -f /etc/nftables/vpn-hook.nft
Който и механизъм да изберете, дръжте критичната секция кратка и я направете повторно входима: кука, която се проваля по средата, трябва да е безопасна за повторно изпълнение. Записвайте резултата, за да се вижда повторното изпълнение в журнала, вместо да се извежда от брой правила. Ако двама различни супервизора могат да извикат куката, поправете това първо; никаква ключалка не поправя двама собственици.
Разглобявайте само това, което притежавате
Разглобяването трябва да различи заместваща връзка от тази, която е пенсионирало, и трябва да преживее събитие, което никога не получава любезно почистване. Изтривайте по същите идентификатори, които сте използвали за добавяне, и никога не изчиствайте споделена верига, за да опростите почистването. След твърдо спиране пуснете проход за съгласуване при следващото стартиране, вместо да предполагате, че куката за спускане е работила.
iptables -D VPN_HOOK -i tun0 -p tcp --dport 443 -j ACCEPT
iptables -F VPN_HOOK
ip -brief link show type tun
Животът на интерфейса също е част от дизайна. Повторно свързване може да създаде устройство с друго име, така че правило, което твърдо задава името на втория тунел, остарява, докато още изглежда валидно. Предпочитайте идентичността, която самата връзка разкрива, и я препрочитайте при всяко изпълнение. Тествайте трите събития поотделно: повторно свързване, заместващо свързване и изключване. Разрешената мрежова дейност трябва да преживее и трите без дубликати, а несвързаните услуги трябва да останат недокоснати.
Разходката свършва, когато куката има собственик, тест за всяко добавено правило, един сериализиран път и разглобяване, което премахва само собственото ѝ състояние. Кука, която е безопасна за два пъти, струва повече от кука, която е умна веднъж.