Вопрос или проблема
У меня есть VPS (KVM) сервер с Debian bullseye и публичным IP. Этот сервер также работает как сервер wireguard. Дома у меня есть еще один сервер (за NAT) с клиентом wireguard, который подключен к моему VPS. Тоннель работает, что означает, что я могу правильно общаться через VPN wireguard.
+----------------------------------+ +-------------------------------
| Домашний сервер (за NAT) | | VPS (KVM) с публичным IP |
| 192.168.1.10 | | 1.2.3.4 |
| +------------------------| |--------------------+ |
| | wg-homeserver | - - - - - - | wg-vps | |
| | 192.168.200.2 | | 192.168.200.1 | |
| +------------------------| |--------------------+ |
| | | |
+----------------------------------+ +------------------------------+
Мой домашний сервер запускает несколько контейнеров Docker, которые прослушивают порты (на всех IP-адресах), что означает, что эти порты доступны из 192.168.1.0/24. Теперь мне нужно перенаправить один TCP и один UDP порт на публичном IP-адресе моего VPS и перенаправить трафик через ссылку wireguard на те же порты на моем домашнем сервере:
1.2.3.4:10000/tcp -> 192.168.200.2:10000/tcp
1.2.3.4:10001/udp -> 192.168.200.2:10001/udp
IP-проброс включен на обеих машинах, что означает, что cat /proc/sys/net/ipv4/ip_forward
показывает 1
.
Чтобы перенаправить TCP-порт, у меня есть эти правила:
iptables -A FORWARD -d 192.168.200.2/32 -i wg-vps -p tcp --dport 10000 -j ACCEPT
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 10000 -j DNAT --to-destination 192.168.200.2:10000
Когда я пытаюсь выполнить ssh -p 10000 1.2.3.4
, я не вижу никаких пакетов, которые регистрируются wireguard -i wg-vps
. Я пробовал множество других вещей, но не смог выяснить, что я делаю неправильно или чего мне не хватает.
Что касается UDP-порта, я создал это правило, с чуть большей успешностью:
iptables -t nat -A PREROUTING -d 1.2.3.4/32 -i eth0 -p udp --dport 10001 -j DNAT --to-destination 192.168.200.2:10001
Вот как я отправляю свой тестовый UDP-пакет:
echo -n test | nc -4 -u 1.2.3.4 10001
Когда я это делаю, я вижу, что tcpdump -i wg-vps
на моем VPS регистрирует это (4.5.6.7
– это мой публичный IP-адрес):
11:35:47.497622 IP 4.5.6.7.43357 > 192.168.200.2.10001: UDP, длина 4
Что-то похоже на то, что он пытается сделать правильные вещи, взять пакет, обновить адрес назначения на 192.168.200.2
и затем передать его на интерфейс wireguard wg-vps
. Но tcpdump -i wg-homeserver
на моем домашнем сервере никогда не показывает, что этот пакет приходит.
На самом деле, я заметил, что когда я watch ip -s link show wg-homeserver
на моем домашнем сервере, каждый раз, когда я отправлял UDP-пакет на этот порт, количество RX ошибок увеличивалось на один. Так что что-то доходит до туда, но что бы это ни было, это не отображается с tcpdump
и, похоже, теряется где-то ниже. Что странно, потому что и UDP, и TCP через ссылку wireguard работают отлично в обе стороны.
Насколько я понимаю, tcpdump
показывает пакеты перед iptables, так что, по моему предположению, даже если пакет, кажется, записан в интерфейс wireguard, он где-то теряется.
ОБНОВЛЕНИЕ:
Окей, я нашел способ включить ведение журнала wireguard:
echo module wireguard +p > /sys/kernel/debug/dynamic_debug/control
И когда я просматриваю журналы с dmesg --follow
, похоже, что wireguard отбрасывает пакет по следующей причине:
wireguard: wg-homeserver: Пакет имеет ненадлежащий исходный IP (4.5.6.7) от пира 20 (xxxxxx)
Так что я думаю, что это значит, что ему не нравится тот факт, что адрес источника – оригинальный адрес откуда запрос пришел. Я не хочу делать SNAT, поэтому, похоже, мне нужно как-то научить его, что он должен разрешать любой исходный адрес.
Что оказывается является настройкой AllowedIPs
в разделе [Peer]
моей конфигурации wireguard. Это решает проблему:
AllowedIPs = 0.0.0.0/0, ::0/0
Ранее я установил маски интерфейса подобно тому, что есть в разделе [Interface]
, не осознавая, что это ограничит исходные адреса пакетов.
Однако это перехватывает весь трафик и пытается маршрутизировать его через ссылку wireguard, так как wg-quick
смотрит на AllowedIPs
и считает, что должен добавить маршрут и перенаправить весь трафик через VPN. Это явно не желательно, но, к счастью, есть решение: добавление Table = off
в раздел [Interface]
предотвратит это.
Посмотрите на свою таблицу правил, чтобы понять, как маршрутизируются исходящие пакеты на домашнем сервере. wg-quick добавит некоторые правила.
ip rule show
Для меня мне пришлось удалить некоторые правила, сгенерированные wg-quick (которые заставляют перенаправлять все пакеты на wg) и затем добавить правила, которые перенаправляют необходимые порты. Вы можете увидеть wg таблицу из предыдущей команды.
ip -4 rule add sport 80 table XXXXX
ip -4 rule add sport 443 table XXXXX
Вышеуказанное работало некоторое время. Но systemd-networkd будет удалять пользовательские правила, когда истекает аренда DHCP или когда сетевой кабель отключается и подключается снова. Поэтому я полностью удалил wg-quick и использую systemd-networkd для настройки интерфейса wg и правил маршрутизации.
Ответ или решение
Чтобы перенаправить UDP и TCP порты на сервер, находящийся за VPN-соединением WireGuard, необходимо правильно настроить правила iptables на вашем VPS и внести соответствующие изменения в конфигурацию WireGuard. Давайте подробно разберём весь процесс, учитывая все нюансы.
1. Структура сети
Имеется VPS с публичным IP (1.2.3.4), который работает как сервер WireGuard (wg-vps). На домашнем сервере (192.168.1.10), находящемся за NAT, установлен WireGuard-клиент (wg-homeserver). Успешная работа VPN-соединения подтверждается наличием рабочего интерфейса:
- Homeserver: 192.168.1.10
- WireGuard домашнего сервера: wg-homeserver (192.168.200.2)
- VPS: 1.2.3.4
- WireGuard VPS: wg-vps (192.168.200.1)
2. Настройка iptables на VPS
Для перенаправления TCP и UDP трафика с публичного IP вашего VPS на доменный сервер, выполните следующие команды iptables:
Перенаправление TCP
iptables -A FORWARD -d 192.168.200.2/32 -i wg-vps -p tcp --dport 10000 -j ACCEPT
iptables -t nat -A PREROUTING -d 1.2.3.4/32 -i eth0 -p tcp --dport 10000 -j DNAT --to-destination 192.168.200.2:10000
Перенаправление UDP
iptables -A FORWARD -d 192.168.200.2/32 -i wg-vps -p udp --dport 10001 -j ACCEPT
iptables -t nat -A PREROUTING -d 1.2.3.4/32 -i eth0 -p udp --dport 10001 -j DNAT --to-destination 192.168.200.2:10001
3. Проверка ip_forward
Убедитесь, что IP-форвардинг включен на обоих серверах:
cat /proc/sys/net/ipv4/ip_forward
4. Конфигурация WireGuard
Важно настроить допустимые IP-адреса в конфигурации WireGuard на домашнем сервере, чтобы избежать блокировки пакетов с непозволенными IP-адресами. В секции [Peer]
вашей конфигурации WireGuard на домашнем сервере измените AllowedIPs
на следующие параметры:
AllowedIPs = 0.0.0.0/0
Это позволит принимать пакеты с любого IP-адреса.
Чтобы предотвратить перенаправление всего трафика через VPN, добавьте в секцию [Interface]
следующее:
Table = off
5. Правила маршрутизации
Для разделения трафика и маршрутизации только необходимых портов можно использовать правила ip rule
:
ip rule add sport 10000 table 100
ip rule add sport 10001 table 100
6. Использование systemd-networkd
Если вы сталкиваетесь с проблемами, связанными с DHCP и восстановлением соединения, рассмотрите возможность переключения на systemd-networkd
для управления интерфейсами WireGuard и маршрутизации. Это может помочь стабилизировать правила маршрутизации.
7. Дополнительная диагностика
Если после вышеуказанных изменений пакеты все еще не доходят до домашнего сервера, используйте tcpdump
для диагностики на обоих интерфейсах (wg-vps
и wg-homeserver
). Проверьте dmesg
на наличие сообщений от WireGuard о блокировке пакетов и по необходимости внесите корректировки в AllowedIPs
.
Заключение
Применяя вышеописанные шаги, вы сможете настроить переадресацию трафика TCP и UDP с VPS на домашний сервер, находящийся за VPN. Убедитесь, что все правила правильно применены и протестируйте соединение для проверки работоспособности. Если у вас есть дополнительные вопросы или сложности, не стесняйтесь обращаться за помощью.