Правила с пересылкой всех портов могут поглотить ваш слушатель WireGuard
Широкое правило пересылки может поглотить собственные слушатели WireGuard и SSH шлюза. Выберите узкие правила или отдельный публичный адрес, а затем проверьте путь управления.
Публичный шлюз уже запускает WireGuard на UDP 51820, SSH на 22 и одно приложение, которое должно быть доступно из интернета. Заманчивое правило пересылает каждый порт пиру и объявляет дело сделанным. На шлюзе WireGuard такое правило может перехватить транспорт самого туннеля и запереть вас снаружи машины, которая его завершает. Публикация — это решение о маршрутизации с исключением для плоскости управления, а не одна строка DNAT.
Публичный вход или вход через туннель: выберите одно
Публикация сервиса создаёт новую точку входа в интернете. Это не то же самое, что выдать пиру членство в VPN, потому что посетитель никогда не входит в туннель, а шлюз становится публичным лицом бэкенда. Это различие определяет аудиторию правила и его сертификат.
Административные интерфейсы редко уместны на этом месте. Страница администрирования, доступная авторизованным клиентам VPN, держит поверхность атаки внутри туннеля и не выставляет форму входа на произвольное сканирование. Публичным конечным точкам приложения всё равно нужны собственный сертификат TLS, аутентификация и ограничение скорости; зашифрованный участок WireGuard не защищает путь посетителя до шлюза.
Если сервис действительно должен быть публичным, запишите имя хоста, сертификат, который его покрывает, и диапазоны посетителей, которым нужно до него добраться. Эти три факта позже определяют форму правила и политику фильтрации. Всё за их пределами — расширение области на публичном слушателе.
Один порт внутрь, один бэкенд наружу
Используйте один публичный порт и один сервис бэкенда. В этом примере eth0 несёт публичный адрес 198.51.100.20, адрес туннеля шлюза — 10.200.0.1, а пир запускает приложение на 10.200.0.7. Публичный TCP 9443 отображается на TCP 8443 пира:
iptables -t nat -A PREROUTING -i eth0 -d 198.51.100.20 -p tcp --dport 9443 -j DNAT --to-destination 10.200.0.7:8443
iptables -t nat -A POSTROUTING -o wg0 -d 10.200.0.7 -p tcp --dport 8443 -m conntrack --ctorigdst 198.51.100.20 --ctorigdstport 9443 -j SNAT --to-source 10.200.0.1Правило SNAT совпадает с транслированным бэкендом и исходным публичным назначением, поэтому другое соединение к тому же сервису бэкенда остаётся вне этого отображения. Оно также скрывает адрес посетителя от пира, и это тот компромисс, из-за которого маршрутизированный обратный путь с сохранением источника становится отдельной схемой. Справочник по расширениям iptables описывает обе цели и их параметры сопоставления.
Пересылка всё ещё должна быть включена, а цепочке фильтра нужно разрешение для транслированного назначения и порта плюс установленных ответов. Цепочка FORWARD видит транслированное назначение после DNAT, поэтому правило, написанное по публичному адресу, не совпадает с пересылаемым пакетом. Пишите разрешение по кортежу бэкенда, а не по публичному.
Пир должен принимать соединение сервиса с адреса туннеля шлюза и отправлять ответ обратно через туннель. Его AllowedIPs должен разрешать источник, который он действительно получает, а при трансляции источника это адрес туннеля шлюза, и широкая запись 0.0.0.0/0 на каждом пире для этой схемы не требуется. Обратный трафик сбрасывает пир, в списке которого нет этого адреса, либо схема с сохранением источника, которая вместо этого пересылает адрес самого посетителя, поэтому проверяйте источник, который пир действительно видит, а не тот, что в вашем правиле.
Держите собственные слушатели шлюза вне правила
Замените сопоставление порта правилом, покрывающим любое назначение TCP и UDP, и собственный сокет WireGuard шлюза попадёт внутрь. Трансляция назначения происходит до того, как машина решит, что пакет локальный, поэтому UDP 51820 может оказаться у пира, а не у процесса, который держит все соединения пиров. Правило загружается успешно, а туннель умирает, и это отказ, который трудно прочитать со стороны пира.
SSH, агенты мониторинга и любой другой сервис на шлюзе подвержены тому же. Правило, пересылающее всё, не отличает плоскость управления от опубликованного приложения, и первый перезапуск после изменения — это момент, когда блокировка становится очевидной. Правило, захватывающее всё, не предупреждает о сервисе, который оно молча забирает. Вы узнаёте об этом, когда следующее соединение не проходит.
Если широкая пересылка действительно нужна, зарезервируйте порты управления до правила, захватывающего всё, или используйте отдельный публичный адрес для публикации. Второй вариант чище, потому что адрес управления сохраняет собственную политику, но провайдер должен выдать этот адрес; добавление записи DNS его не выделяет.
Широкая пересылка TCP и UDP — это тоже не все протоколы. ICMP, IPv6, обратная связь path-MTU и внешний транспорт VPN нуждаются в собственной политике, а правило, покрывающее TCP и UDP, оставляет эти случаи цепочке по умолчанию.
Выберите модель до того, как писать правила
Четыре формы покрывают большинство публикаций со шлюза, и выбор зависит от того, сколько сервисов вы запускаете и какой риск в плоскости управления вы терпите. Таблица ниже упорядочивает их от самой узкой к самой широкой.
| Model | What it protects | Cost | Use when |
|---|---|---|---|
| Narrow port forward | Every other listener, including the VPN | One rule per service | Few services, stable ports |
| Catch-all with reserved ports | Ports named in the exception list | Rule order becomes critical | Many services and disciplined review |
| Separate public address | Control address fully isolated | Provider must supply the address | High-value publication |
| VPN-only access | No public entry at all | Visitors need the tunnel | Admin interfaces and internal tools |
Начните с узкой модели, даже если ожидаете больше сервисов позже. Её проще всего проверять, а превратить набор узких правил в проверенное правило, захватывающее всё, проще, чем выяснять, какой слушатель захватило широкое правило. Какую бы модель вы ни выбрали, держите правила у владельца межсетевого экрана. Применение строк iptables рядом с конфигурацией UFW или nftables, которая управляет теми же цепочками, даёт политику, меняющуюся в зависимости от порядка загрузки.
Докажите и публикацию, и путь управления
Проверяйте с авторизованного внешнего клиента, используя одобренное имя хоста и действующий для него сертификат. Подтвердите, какой бэкенд ответил, затем проверьте, что несвязанные публичные порты по-прежнему закрыты. Отключённая проверка сертификата — это не пройденный тест HTTPS, а соединение, попадающее не на тот бэкенд, хуже неудачного.
После этого проверьте сам шлюз: подключите пир WireGuard, откройте сеанс SSH и убедитесь, что мониторинг по-прежнему отчитывается. Опубликованный сервис может работать, пока плоскость управления сломана, поэтому обе проверки относятся к одному окну изменений. Перезагрузите один раз, чтобы доказать, что правила применяются заново в ожидаемом порядке, затем снимите публикацию и убедитесь, что удаление действительно соответствует добавлению. Большой набор добавлений при загрузке с неполным удалением — это то, как временная проверка становится постоянной дырой.