Один клиент на вашем сервере 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-сессии.

Похожие статьи