Ограничьте правило SNAT для OpenVPN, прежде чем оно сломает nginx
Клиенты проходят аутентификацию, но ничего не маршрутизируется, или сайт падает после поднятия VPN. Проверьте доступ к tun, затем ограничьте трансляцию пулом и одним интерфейсом.
Две неисправности постоянно приходят с одного и того же типа хоста. В первой клиенты аутентифицируются и затем не достигают ничего за пределами туннеля. Во второй VPN поднимается, и собственный сайт сервера перестаёт отвечать, что тревожнее всего, потому что похоже на сопутствующий ущерб. На VPS на основе контейнеров обе обычно сводятся к одному и тому же короткому списку проверок, и порядок важен: сначала устройство, затем трансляция, потом охват.
Убедитесь, что контейнер может создать устройство tun
Ничто другое не имеет значения, если туннельный интерфейс не может существовать. Проверьте, что /dev/net/tun присутствует и что создание тестового устройства удаётся, потому что многие провайдеры по умолчанию отключают tun внутри контейнеров. Никакая работа с firewall не компенсирует устройство, которое так и не было создано.
Если устройства нет, включить его могут только хост или провайдер. Другой тариф часто дешевле, чем открытая тема поддержки, длящаяся неделю. Убедитесь в этом, прежде чем читать хотя бы одну строку лога OpenVPN. Иначе вы проведёте вечер, настраивая правила, которые никогда не увидят пакет.
Решите, что MASQUERADE делает на этом интерфейсе
На обычной виртуальной машине обычное правило выхода — это POSTROUTING MASQUERADE из основного интерфейса. В контейнере OpenVZ видимое устройство часто venet0, виртуальный интерфейс под управлением хоста, а не маршрутизируемая сетевая карта, и MASQUERADE там ведёт себя не всегда так, как предполагают руководства.
Работоспособная форма — явная трансляция на адрес, до которого клиенты уже доходят, с разрешённой пересылкой в обе стороны. Замена пула из конфигурации сервера так же важна, как замена адреса. Прочитайте каждую строку, прежде чем вставлять её.
iptables -t nat -A POSTROUTING -o venet0 -s 10.8.0.0/24 -j SNAT --to-source 203.0.113.10
iptables -A FORWARD -i tun0 -j ACCEPT
iptables -A FORWARD -o tun0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPTБез правил пересылки трансляция всё равно происходит, а ядро всё равно отказывается пересылать. Это сочетание создаёт запутанное состояние, когда счётчики на правиле NAT растут, а клиент ничего не получает. Две строки FORWARD тоже должны стоять перед любым широким правилом drop в той же цепочке. Порядок — часть конфигурации, а не деталь реализации.
Ограничьте правило одним пулом и одним интерфейсом
У второго симптома другая причина: правило POSTROUTING без ограничения источника и без ограничения выхода. Такое правило переписывает каждый пакет, покидающий хост.
Службы, зависящие от исходного источника, после этого ведут себя неправильно. Веб-сервер за локальным прокси может перестать отвечать, и перезапуск ничего не меняет, потому что правило всё ещё на пути. Затрагивается и трафик, который хост отправляет на собственный публичный адрес, поэтому сбой может выглядеть как проблема DNS или сертификата, а не firewall. Правило почти наверняка добавили, чтобы исправить первый симптом.
Решение — сузить совпадение до пула туннеля и выходного интерфейса, а затем добавить по одному правилу на пул вместо расширения одного правила на несколько.
Сделайте правила постоянными и выясните, кто ещё ими владеет
Правила, добавленные вручную, исчезают при перезагрузке, поэтому сохраните их с помощью iptables-save или управляйте ими через netfilter-persistent там, где он установлен. Убедитесь, что восстановление выполняется до запуска OpenVPN. Затем один раз намеренно перезагрузитесь, вместо того чтобы обнаружить пробел во время инцидента.
На хосте с контейнерами также убедитесь, что файл сохранения находится в записываемом хранилище контейнера и что провайдер не заменяет фильтрацию при загрузке. Некоторые платформы управляют политикой вне контейнера, где локальные правила либо игнорируются, либо конфликтуют с правилами самого хоста.
Проверьте счётчиками и одним перехваченным потоком
С подключённого клиента проверьте публичный адрес, который сообщает внешняя служба. Если он совпадает с адресом сервера, трансляция работает; если нет, пакет уходит другим путём или не уходит вообще. Затем проверьте и службу на сервере, и службу в публичном интернете, потому что они идут разными путями через один и тот же набор правил.
На сервере прочитайте счётчики пакетов на правилах NAT и FORWARD с помощью iptables -t nat -L -v -n и понаблюдайте за одним потоком в перехвате. Если адрес клиента появляется в перехвате и ответ не следует, пробел на обратном пути или в фильтрации провайдера, а не в профиле клиента. Сравните перехваченный источник с адресом, на который транслирует правило, потому что расхождение означает, что раньше совпало другое правило. Один наблюдаемый поток решает больше, чем страница чтения конфигурации.
Держите пул, транслированный адрес и имя интерфейса вместе в журнале изменений. Правило, верное для одного пула, неверно транслирует следующий.