Заблокувати один діапазон призначення для кожного пулу клієнтів VPN
Одне правило nftables може відхилити префікс призначення для допущеного пулу VPN, не торкаючись власного трафіку шлюзу. Узгодьте хук і позицію.
Одне правило може утримати допущений пул VPN осторонь діапазону призначення, не заважаючи нічому іншому, що робить шлюз. Саме правило коротке; чи працюватиме воно, вирішують хук, у якому воно живе, і його позиція в ланцюжку. Помилка в цих двох дає міжмережевий екран, який виглядає правильно і поводиться непослідовно. Почніть із того, що робить пакет, коли правило його бачить.
Що правило насправді зіставляє
Правило зіставляє три речі одночасно: вхідний інтерфейс, префікс джерела і префікс призначення. Усі три мають бути істинними, перш ніж застосується drop, і саме це робить його вузьким. Читати його як один вираз простіше, ніж як три окремі політики.
Зіставлення інтерфейсу відрізняє перенаправлений клієнтський трафік від власних з'єднань шлюзу. Без нього правило, що називає лише пул джерела, зачепило б і пакети, які шлюз сам створює з цієї адреси, якщо таке колись станеться. Префікс джерела обмежує політику допущеними клієнтами, а префікс призначення — одним діапазоном. Читайте правило як перетин, а не як список.
Запишіть три значення, перш ніж будь-що змінювати: назву тунельного інтерфейсу, пул, який видає сервер, і префікс, який ви збираєтеся відхилити. Друкарська помилка в будь-якому з них дає правило, яке чисто розбирається і нічого не захищає. Тримайте ці три значення в записі про зміну поряд із правилом.
Хук вирішує, на кого поширюється правило
Ланцюжок netfilter приєднаний до хука, і саме хук вирішує, які пакети ланцюжок узагалі бачить. Хук forward бачить трафік, що маршрутизується через шлюз, а це і є трафік від клієнта до призначення. Усе інше в ланцюжку націлене на іншу аудиторію.
Хук input бачить трафік, адресований самому шлюзу, тому правило, розміщене там, керує доступом до його власних служб, а не транзитом. Хук output бачить трафік, який шлюз породжує сам, і це протилежність тому, що потрібно політиці пулу клієнтів. Назви ланцюжків — довільні позначки, вибрані тим, хто писав набір правил, тому не виводьте хук із назви. Перевірте, куди приєднаний ланцюжок, перш ніж припускати, що він може зіставити.
| Hook | Traffic it sees | Right for this policy |
|---|---|---|
| input | Addressed to the gateway | No, that is the host's own services |
| forward | Routed through the gateway | Yes, for client-to-destination traffic |
| output | Generated by the gateway | No, that is the opposite direction |
Читання приєднання — перевірка в один рядок, яка не дає правилу потрапити в ланцюжок, що ніколи не бачить пакет.
Розмістіть правило перед широким accept
Правила оцінюються по порядку, і перший вердикт перемагає. Широкий accept вище в ланцюжку завершує оцінку для пакетів, які він зіставляє, тому drop, доданий пізніше, для них ніколи не виконується. Це правило порядку — уся причина того, чому правильно виглядаюче правило може не давати ефекту.
Вставте правило перед accept, а не додавайте його в кінець. Якщо ланцюжок уже містить загальний accept для тунельного інтерфейсу, нове правило має стояти перед ним, інакше воно лише прикраса. Перевіряйте отриманий порядок, а не файл, який ви редагували, бо набір правил, зібраний із кількох файлів, може не відповідати жодному з них. Потім підтвердьте тестовим пакетом із пулу.
sudo nft list chain inet filter forward
sudo nft insert rule inet filter forward iifname "tun0" ip saddr 10.90.0.0/24 ip daddr 198.51.100.0/24 drop
sudo nft -c -f /etc/nftables.conf
Третя команда розбирає файл, не застосовуючи його, і ловить синтаксичні помилки, перш ніж вони стануть збоєм. Застосовуйте з планом відкату, бо помилкове правило в ланцюжку forward може перерізати тунель, через який ви працюєте.
Наявні потоки не зважають на ваше нове правило
Запис conntrack, створений до появи правила, продовжує відповідати попередньому accept. Тому новий drop іноді виглядає працюючим для нових з'єднань і нічого не робить для того, яке перевіряють.
Прочитайте зіставлення стану на початку ланцюжка. Якщо воно приймає трафік established і related до вашого правила, кожен уже наявний потік тече далі, доки не закриється. Зазвичай це саме та поведінка, яку ви хочете для аварійного правила, і вона заплутує, коли ви чекаєте негайного обриву. Вирішіть, який ефект вам потрібен, перш ніж розгортати. Тест, який повторно використовує відкрите з'єднання, розповість вам неправильну історію.
sudo conntrack -L -s 10.90.0.14 -d 198.51.100.20
sudo nft list ruleset | grep -n -A3 'ct state'
Перша команда показує, чи існує потік, а друга — чи продовжує раннє правило стану його приймати. Обидві лише для читання і безпечні під час інциденту.
Чим це правило не є
Правило не є чорним списком доменів, політикою IPv6 або обмеженням для окремого облікового запису застосунку.
Кожному з цього потрібен свій механізм. Блокування домену має розв'язувати імена, чого фільтр пакетів не робить. Трафіку IPv6 потрібне власне зіставлення, бо вираз ip нічого не каже про пакети ip6. Обмеження на рівні застосунку належить службі або автентифікованому проксі, а не зіставленню префікса. Саме розділення цих вимог не дає покласти чотири завдання на одне вузьке правило.
Контракт, який дає це правило, точний: трафік із допущеного пулу до одного префікса призначення відхиляється, а незв'язаний трафік шлюзу зберігає свою поточну політику. Запишіть це речення поряд із правилом, і наступна людина знатиме, для чого воно було.