Вопрос или проблема
Я новичок в iptables.
У меня есть docker-контейнер wg-easy с локальным IP 172.18.0.2. У моего VPS публичный IP 185.217.198.123. Также есть ip route add 10.8.0.0/24 via 172.18.0.2
для доступа к peer-ам wireguard напрямую с VPS. У них диапазон 10.8.0.0/24.
По сути, я хочу ‘перенаправить’ все udp пакеты, которые приходят с 185.217.198.123:19132 на 10.8.0.2:19132 и наоборот.
Назовем удаленное устройство, которое хочет получить доступ к 185.217.198.123:19132, клиентом.
iptables -t nat -L
:
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
DNAT udp -- anywhere anywhere udp dpt:19132 to:10.8.0.2:19132
DOCKER all -- anywhere anywhere ADDRTYPE match dst-type LOCAL
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
DOCKER all -- anywhere !localhost/8 ADDRTYPE match dst-type LOCAL
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE all -- 172.17.0.0/16 anywhere
MASQUERADE all -- 172.18.0.0/16 anywhere
MASQUERADE udp -- 172.18.0.2 172.18.0.2 udp dpt:51820
MASQUERADE tcp -- 172.18.0.2 172.18.0.2 tcp dpt:51821
SNAT udp -- anywhere 10.8.0.2 udp dpt:19132 to:185.217.198.123
Chain DOCKER (2 references)
target prot opt source destination
RETURN all -- anywhere anywhere
RETURN all -- anywhere anywhere
DNAT udp -- anywhere anywhere udp dpt:51820 to:172.18.0.2:51820
DNAT tcp -- anywhere anywhere tcp dpt:51821 to:172.18.0.2:51821
Когда клиент подключен к vpn (wg-easy docker-контейнер), все работает как предполагалось.
Логи tcpdump
:
15:41:23.412635 IP 172.18.0.2.56489 > 185.217.198.123.19132: UDP, length 4
15:41:23.412666 IP 185.217.198.123.56489 > 10.8.0.2.19132: UDP, length 4
15:41:23.507247 IP 10.8.0.2.19132 > 185.217.198.123.56489: UDP, length 4
15:41:23.507275 IP 185.217.198.123.19132 > 172.18.0.2.56489: UDP, length 4
Обратите внимание, что все пакеты приходят из docker-контейнера wg-easy (172.18.0.2).
Но когда клиент
не подключен к vpn и хочет получить прямой доступ к vps, происходит следующее:
15:58:31.459491 IP (ip клиента).(случайный порт) > 185.217.198.123.19132: UDP, length 4
и на этом все. Продолжения здесь нет. Почему это происходит и как это исправить?
Ответ или решение
Ваша ситуация с iptables связана с трансляцией и переадресацией сетевых пакетов; это проблема, которую часто встречают начинающие администраторы систем. Давайте рассмотрим вашу ситуация более детально и попытаемся определить, почему ваши правила iptables работают, когда запросы идут через VPN, и почему они не срабатывают, когда клиент пытается подключиться напрямую.
Теория
Сначала разберёмся, как работают iptables и как они взаимодействуют с сетевой топологией вашей системы. Iptables — это межсетевой экран, который управляет IP-трафиком в системе на Linux. Он состоит из нескольких цепочек, причем в вопросе задействованы такие как PREROUTING, POSTROUTING, INPUT, OUTPUT и FORWARD, каждая занимается обработкой пакетов на различных стадиях прохождения через ваш сервер.
PREROUTING и POSTROUTING цепи
- PREROUTING — используется для изменения пакетов после того, как они поступают на интерфейс сети, но до маршрутизации.
- POSTROUTING — применяется к пакетам после выполнения маршрутизации и перед тем, как они покинут интерфейс сети.
DNAT и SNAT
- DNAT (Destination Network Address Translation) — изменяет адрес назначения пакета. Используется в цепочке PREROUTING для перенаправления входящего трафика на другой IP и порт.
- SNAT (Source Network Address Translation) — изменяет адрес источника пакета. Это чаще всего делается в POSTROUTING, чтобы корректно возвращать трафик клиенту за NAT.
Пример
Например, вы имеете следующее правило для DNAT:
DNAT udp -- anywhere anywhere udp dpt:19132 to:10.8.0.2:19132
Это правило указывает, что любой UDP трафик, поступающий на порт 19132, должен быть перенаправлен на адрес 10.8.0.2 с тем же портом. Это работает идеально, когда ваш клиент подключён через VPN, так как сетевые пакеты проходят через интерфейс Docker и обрабатываются правилами это контейнера.
Однако, при непосредственном подключении проблема в том, что трафик от клиента достигает вашего публичного IP-адреса, но не перенаправляется корректно. Это может быть связано с тем, как пакет обрабатывается в цепочках iptables или какое конкретное назначение ему присваивается после прохождения NATа.
Применение
Для решения вашей проблемы, рассмотрите следующее:
-
Убедитесь, что все пакеты корректно правая через цепочки PREROUTING и POSTROUTING. Добавьте журналирование (логирование) в iptables, чтобы определить, где именно пакеты "застревают":
iptables -t nat -A PREROUTING -p udp --dport 19132 -j LOG --log-prefix "PREROUTING: " iptables -t nat -A POSTROUTING -p udp --dport 19132 -j LOG --log-prefix "POSTROUTING: "
-
Убедитесь, что нет конфликтующих правил в других цепочках, таких как INPUT или FORWARD, которые могут блокировать или изменять пакеты. Проверьте политику по умолчанию для всех цепочек.
-
Проверьте и исправьте правил SNAT. Возможно, они неправильно настроены для пакетов, которые должны возвращаться клиенту, что мешает им достигнуть нужного получателя.
-
Маршрутизация. Проверьте, что ваша маршрутизация корректно настроена для всех интерфейсов и диапазонов адресов.
ip route add
действует только в контексте от интерфейса wireguard; убедитесь, что для других интерфейсов тоже существует корректная маршрутизация. -
Пересмотр NAT правил. Вместо использования SNAT и MASQUERADE для данной задачи, подумайте об использовании PAT (Port Address Translation), чтобы исключить нежелательные эффекты от NAT.
-
Проверка сервисов. Убедитесь, что целевой сервис на IP 10.8.0.2 действительно слушает порт 19132 и в состоянии обработать входящие пакеты. Можете использовать
nc
для проверки доступности через контейнер. -
Таблица маршрутизации. Проверьте и перепроверьте свои статические маршруты с помощью команды
ip route show
, чтобы убедиться, что пересылка пакетов настроена корректно.
Проверка этих предложений должна помочь вам изолировать и исправить проблему, почему ваш трафик не переадресуется должным образом в случае с подключениями вне VPN.