Один клієнт на вашому сервері OpenVPN має втратити доступ до LAN, поки всі інші тунелі працюють. Якщо пошукати, найкраща відповідь зазвичай каже, що демон цього не може, і це лише половина правди: у OpenVPN немає брандмауера для кожного клієнта, але хост, що завершує тунель, уже фільтрує пакети. Два рішення, які важливі, — це особа, яку ви блокуєте, і позиція правила. Зробіть це правильно, і зміна стане одним рядком, який можна перевірити й видалити.

Прив'яжіть клієнта до того, як писати правило

OpenVPN здає тунельні адреси з пулу, тож 10.8.0.6 — це місце, а не людина. Коли сесія завершується, оренда повертається і може дістатися наступному з'єднанню, тобто правило, написане проти цієї адреси, слідує за місцем, а не за користувачем. Тому спершу вирішіть, що саме блокуєте: адресу для короткого експерименту чи сертифікат того, кого хочете тримати зовні.

Щоб прив'язати адресу до сертифіката, створіть файл у каталозі, який задає client-config-dir, і дайте файлу точно common name сертифіката. Впишіть у нього одну директиву, ifconfig-push 10.8.0.6 255.255.255.0, і цей клієнт зберігатиме ту саму тунельну адресу між перепідключеннями. Щоб це працювало, потрібні два налаштування: client-config-dir має бути оголошений у конфігурації сервера, а адреса, що надсилається, має лежати в підмережі, яку сервер може маршрутизувати. Пропустіть одне — і файл буде проігноровано без помилки, що зробить наступну перевірку брандмауера оманливою.

Тимчасове блокування може використовувати адресу з пулу, якщо в заявці записано, яка сесія тримала її на той момент.

Порядок вирішує, чи виконається скидання

На Linux-шлюзі, який пересилає між тунелем і LAN, пакети проходять ланцюг FORWARD. Читайте команду нижче як речення: вставити на початок FORWARD, зіставити трафік, що входить з tun0, від цього одного хоста, скерований у підмережу LAN, і відкинути його.

iptables -I FORWARD -i tun0 -s 10.8.0.6/32 -d 192.168.1.0/24 -j DROP

-I — це те, що змушує правило працювати. Додане через -A, воно опиняється нижче будь-якого широкого дозволу для підмережі тунелю і ніколи не бачить пакета. Перевірте позицію за допомогою iptables -vnL FORWARD --line-numbers і прочитайте також лічильники: скидання на початку, яке нічого не рахує, означає, що трафік надходить іншим шляхом.

Власна LAN-адреса шлюзу — це інший шлях. Пакети, надіслані самій коробці, йдуть у INPUT, а не в FORWARD, тож клієнт може втратити хост у LAN і все одно відкрити сторінку адміністрування роутера. Додайте відповідне правило INPUT, коли це важливо.

Чого фільтр не бачить

Фільтрування відбувається під час оцінки пакета, тож встановлена TCP-сесія може тривати, доки не закриється або не буде скинута. Якщо блокування має спрацювати негайно, очистіть відстежувані потоки для цього джерела за допомогою conntrack -D -s 10.8.0.6 після вставлення правила. Якщо кілька секунд перекриття прийнятні, зафіксуйте цей вибір, а не залишайте його неявним. У будь-якому разі наступна людина має знати, чи правило зупиняє живий трафік, чи лише нові з'єднання.

Трафік між партнерами ніколи не торкається брандмауера хоста. Коли client-to-client увімкнено, OpenVPN пересилає ці пакети всередині демона, тож їх не бачить ні FORWARD, ні INPUT. Єдині рішення — вимкнути client-to-client або прийняти, що партнери можуть діставати один одного; правило iptables цього трафіку не побачить.

IPv6, прошивка та виживання після перезавантаження

Правило IPv4 нічого не каже про IPv6. Якщо тунель і LAN несуть обидві родини, еквівалентне правило має існувати в ip6tables або в наборі правил nftables, який володіє політикою на цьому хості. Прошивка роутера часто ховає netfilter за власною абстракцією, тож синтаксис і назви таблиць, скопійовані з форуму, можуть не застосовуватися.

На OpenWrt документований шлях — це запис конфігурації брандмауера, а не написаний вручну рядок iptables, і написаний вручну рядок може зникнути під час перезавантаження брандмауера. Інші дистрибутиви відновлюють правила через netfilter-persistent, завантажувальний модуль або сховище виробника, і ці механізми не взаємозамінні. Доведіть вибраний перезавантаженням, бо перезавантаження тренує інший шлях.

Перевірте за шляхами, потім чисто відкатіть

Перевіряйте кожен шлях окремо, бо одна успішна перевірка приховує інші. Заблокований клієнт має далі потрапляти в інтернет через тунель, але зазнавати невдачі щодо хоста в LAN, другий клієнт має досягати того самого хоста, а адреса шлюзу й шлях до партнера потребують кожен свого спостереження. Запишіть результати поруч із правилом, щоб наступна зміна мала базу. Таблиця нижче — це набір, який варто залишити в заявці.

ШляхОчікується з правиломКоли не спрацьовує
Заблокований клієнт до хоста в LANНемає відповідіПравило нижче дозволу, або джерело не збігається
Заблокований клієнт до інтернетуПрацює через tun0Правило занадто широке, без збігу призначення
Другий клієнт до того самого хоста в LANПрацюєПравило збіглося з більшим, ніж задуманий хост
Заблокований клієнт до LAN-адреси шлюзуБлокується лише з відповідним правилом INPUTПравило INPUT відсутнє
Заблокований клієнт до тунельної адреси партнераВсе ще працюєclient-to-client увімкнено і поза межами брандмауера

Відкат — це видалення за специфікацією, а не flush: iptables -D FORWARD -i tun0 -s 10.8.0.6/32 -d 192.168.1.0/24 -j DROP видаляє саме цей запис і залишає решту ланцюга недоторканою. Видаліть той самий рядок із файлу, який відновлює правила під час завантаження, перезавантажте його й підтвердьте, що клієнт знову досягає хоста в LAN. Flush FORWARD скасував би й правила, яких ви не писали, що перетворює відкат на другий інцидент.

Перш ніж закрити заявку, підтвердьте три речі: прив'язана адреса збігається із сертифікатом, правило стоїть вище дозволів із лічильником, відмінним від нуля, і файл збереження містить те саме правило, яке ви перевіряли. Якщо чогось немає, блокування — це ілюзія в shell-сесії.

Схожі статті