Kill switch на маршрутизаторі, що охоплює FORWARD, OUTPUT і IPv6
Kill switch лише в FORWARD залишає маршрутизатор вільним для витоку, а правила лише для IPv4 залишають IPv6 відкритим. Упорядкуйте ланцюги й перевірте з вимкненим тунелем.
Ви входите в маршрутизатор, вставляєте набір правил kill switch із допису на форумі, і LAN перестає переглядати в ту саму мить, коли тунель падає. Через два дні маршрутизатор усе ще оновлює свій динамічний запис DNS через звичайний WAN, а гостьовий ноутбук усе ще досягає сайтів IPv6. Обидві поведінки нормальні, бо вставлені правила охоплювали один ланцюг і одну родину адрес, і жодне з цього не є всім маршрутизатором. Прохід шляхами пакетів по порядку показує саме те, що було пропущено.
Почніть із маршрутизатора, а не з ноутбука
Політика на рівні маршрутизатора приваблива для невеликого офісу, бо кожен пристрій за ним успадковує однакову поведінку і ніхто не може забути ввімкнути перемикач на клієнті. Вона також дає одне місце для перевірки після кожного оновлення прошивки. Чого вона не дає — автоматичного покриття власного трафіку маршрутизатора або другої родини адрес, і саме це дві прогалини за більшістю невдалих розгортань.
Перш ніж щось змінювати, запишіть три факти на папері: назву інтерфейсу WAN, назву мосту LAN, а також адресу й порт кінцевої точки VPN. Усі три знадобляться в правилах, а вгадування назв інтерфейсів — найчастіша причина, чому набір правил, що виглядає правильно, нічого не робить.
Пройдіть три шляхи, які може обрати пакет
Трафік з ноутбука в інтернет пересилається, тому він проходить через ланцюг FORWARD. Трафік, який створює сам маршрутизатор, наприклад пересилання DNS, запити NTP, оновлення DDNS і канал керування VPN, проходить через OUTPUT. Керівний трафік, адресований маршрутизатору, надходить через INPUT.
Отже, kill switch, збудований лише в FORWARD, захищає клієнтів і більше нічого. Таблиця показує, чому витік із початкової сцени передбачуваний, а не загадковий.
| Packet path | Example | Chain that sees it |
|---|---|---|
| LAN client to WAN or tunnel | Browser request | FORWARD |
| Router-originated | DDNS update, NTP | OUTPUT |
| Addressed to the router | SSH from the LAN | INPUT |
У більшості проєктів вам не потрібен kill switch на INPUT, але треба підтримувати керівний доступ робочим, поки тунель вимкнений. Інакше за першої відмови VPN ви їдете до офісу з консольним кабелем.
Упорядкуйте правила так, щоб тунель ще міг піднятися
Робочий kill switch — це список дозволів, що закінчується відмовою, і саме порядок робить його kill switch, а не цеглиною. Спершу дозвольте loopback, кінцеву точку VPN, відповіді для встановлених потоків та інтерфейс тунелю; решту відхиліть останньою.
iptables -A OUTPUT -o lo -j ACCEPT
iptables -A OUTPUT -d 198.51.100.7 -p udp --dport 51820 -j ACCEPT
iptables -A OUTPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -o wg0 -j ACCEPT
iptables -A OUTPUT -o eth0 -j REJECT
Кінцева точка на цьому етапі має бути адресою, а не іменем хоста. Щойно фінальна відмова блокує DNS, правило, що називає ім’я хоста постачальника, більше не можна розв’язати, і тунель більше ніколи не запуститься після перезавантаження. Якщо постачальник змінює кінцеві точки, розв’яжіть ім’я до застосування політики й оновлюйте це правило з того самого скрипта.
Повторіть форму в FORWARD для трафіку клієнтів і розмістіть явне правило керування над відмовою. Тримайте це правило керування вузьким, але досяжним, і підтвердьте його, відкривши другий сеанс SSH перед закриттям першого. Заблокувати себе ззовні під час зміни kill switch трапляється досить часто, щоб це планувати. На маршрутизаторі з WireGuard allowed-ips партнера вирішують, що входить у тунель, а ці правила вирішують, чому дозволено виходити без нього.
IPv6 потрібні власні двері
Усе вище — це IPv4. Якщо у вашій LAN працює IPv6, а тунель несе лише IPv4, кожен охоплений пристрій усе ще має прямий маршрут в інтернет, якого ваші нові правила ніколи не бачать. Ноутбук із подвійним стеком охоче віддасть йому перевагу, і kill switch виглядатиме зламаним лише для того, хто перевіряє з IPv4.
ip6tables -A FORWARD -i br-lan -j REJECT
ip6tables -A OUTPUT -o eth0 -j REJECT
ip6tables -A OUTPUT -o lo -j ACCEPT
Тут порядок теж важливий: дозвіл loopback має йти перед відмовою WAN, інакше локальні служби на маршрутизаторі почнуть дивно відмовляти. Якщо мережа взагалі не використовує IPv6, простіше вимкнути його на WAN і LAN, і не залишиться нічого, що можна забути.
Деякі клієнти VPN встановлюють маршрут за замовчуванням лише для IPv4 і залишають наявний маршрут за замовчуванням IPv6 недоторканим. Перевірте таблицю маршрутизації після підключення тунелю, а не припускайте, що клієнт це залагодив.
Доведіть це з вимкненим тунелем
Зупиніть тунель із маршрутизатора й перевірте з трьох місць у такому порядку:
# systemctl stop wg-quick@wg0
# ip route get 203.0.113.1
# curl -m 5 -sS http://example.com || echo blocked
# iptables -vnL OUTPUT | head
# ip6tables -vnL OUTPUT | head
Пошук маршруту каже, куди пішов би пакет, а лічильники кажуть, чи ваші правила колись спрацьовували. Правило з нулем пакетів після невдалої перевірки нічого не захищає, і звичайна причина — назва інтерфейсу, відмінна від введеної. Перевіряйте трафік, який створює маршрутизатор, явно, бо перевірка з боку LAN не може задіяти OUTPUT.
Визначте режим відмови раніше, ніж він знадобиться. Fail-closed тримає клієнтів поза мережею, доки тунель не повернеться; fail-open відновлює звичайний доступ до WAN і руйнує мету для трафіку, який вам був важливий. Маршрут blackhole до пулу VPN із високою метрикою — корисний другий шар для проєктів fail-closed, оскільки він виживає, коли маршрут тунелю зникає, замість того щоб падати назад на маршрут за замовчуванням.
Приймайте налаштування лише тоді, коли клієнт у LAN, запит, створений маршрутизатором, і запит IPv6 усі зазнають невдачі з вимкненим тунелем, і всі три знову працюють, щойно він піднімається.