Переадресация портов WireGuard из Интернета!
Данный опус является частью единого цикла заметок o CLI. Для его написания использовалось множество различных источников (скилы крутых специалистов, статьи с тематических сайтов, техническая документация, комментарии с форумов и социальных сетей и т. д и т. п.). К сожалению, указать все источники точно не представляется возможным! По этому, в конце заметки, будет указана ссылка только на основной источник. Материалы, использованные для написания заметки, изменялись автором под конкретную задачу! Вам, скорее всего, тоже придется поступить аналогичным образом для получения желаемого результата)
Если у вас есть частный сервер, который не доступен публично из Интернета (например, потому что он находится за NAT), но вы хотите предоставить доступ к работающей на нем службе общедоступному интернет-трафику(подразумевается что у каждого сервиса есть определенный порт), вы можете сделать это через WireGuard — при условии, что у вас есть другой сервер, общедоступный из Интернета. Эта статья покажет вам, как это сделать.
Установить соединение WireGuard между двумя серверами и перенаправить трафик с одного на другой обычно довольно просто.
use add name=имя password=пароль group=full
Часть, которая может быть сложной, — это возврат трафика обратно. Например, предположим, что у вас есть веб-приложение, работающее на порту 8080 частного сервера за NAT (преобразование сетевых адресов) на одном сайте, и вы хотите сделать его доступным для общедоступного Интернета через порт 2000 общедоступного сервера, имеющего домен. имя public.example.com:
Наиболее вероятно, что адресация у Вас будет отличаться, но примерная схема приведенная тут:
На этом частном сервере, чтобы веб-приложение работало правильно, оно должно иметь доступ к серверу базы данных и очереди сообщений в другой внутренней сети, к которой оно подключено; а также вам необходимо иметь возможность доступа к нему из второй внутренней сети для администрирования через SSH. Таким образом, частный сервер не может просто отправлять весь свой трафик через соединение WireGuard на общедоступный сервер — он должен выборочно отправлять обратно к источнику пересылаемого общедоступного трафика только трафик, который представляет собой ответы от его веб-приложения.
Существует несколько различных методов, которые можно использовать для отправки обратного трафика через соединение WireGuard с частного сервера на общедоступный сервер. Какой метод вам нужно использовать, зависит от того, к чему еще нужен доступ частному серверу за пределами его соединения WireGuard. Ниже приведены основные техники:
Basic Connection
Базовое соединение WireGuard между двумя серверами аналогично соединению, описанному в руководстве по настройке WireGuard «точка-сайт» с переадресацией портов.
В этом примере мы настроим WireGuard на нашем частном сервере следующим образом, используя общедоступный IP-адрес общедоступного сервера 203.0.113.2 для запуска соединения WireGuard с общедоступным сервером; и использование параметра PersistentKeepalive для поддержания соединения через NAT, передающий частный сервер:
Примерный файл конфигурации приватного сервера:
# /etc/wireguard/wg0.conf # local settings for the private server [Interface] PrivateKey = AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEE= Address = 10.0.0.1 # remote settings for the public server [Peer] PublicKey = fE/wdxzl0klVp/IR8UcaoGUMjqaWi3jAd7KzHKFS6Ds= Endpoint = 203.0.113.2:51822 AllowedIPs = 10.0.0.2 PersistentKeepalive = 25
Эти настройки аналогичны настройкам «Конечная точка A» из руководства WireGuard «Точка-сайт с переадресацией портов».
На публичном сервере нам нужно включить пересылку пакетов. Нам также необходимо добавить правило брандмауэра для настройки переадресации портов (также известное как DNAT, преобразование сетевых адресов назначения), чтобы преобразовать адрес назначения пакетов, отправленных на TCP-порт 2000 общедоступного сервера, в TCP-порт 8080 на частном сервере (10.0). .0.1). Сделаем это с помощью команд PreUp в его конфиге WireGuard (для удобства):
Вывод команды:
# /etc/wireguard/wg0.conf # local settings for the public server [Interface] PrivateKey = ABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBFA= Address = 10.0.0.2 ListenPort = 51822 # packet forwarding PreUp = sysctl -w net.ipv4.ip_forward=1 # port forwarding PreUp = iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 2000 -j DNAT --to-destination 10.0.0.1:8080 PostDown = iptables -t nat -D PREROUTING -i eth0 -p tcp --dport 2000 -j DNAT --to-destination 10.0.0.1:8080 # remote settings for the private server [Peer] PublicKey = /TOE4TKtAqVsePRVR+5AA43HkAK5DSntkOCO7nYq5xU= AllowedIPs = 10.0.0.1
Эти настройки аналогичны настройкам «Хост β» из руководства WireGuard «Точка-сайт с переадресацией портов».
В нашем примере общедоступного сервера eth0 является его общедоступным сетевым интерфейсом. Флаг -i eth0 в приведенном выше правиле iptables DNAT ограничивает правило сопоставлением только трафика, входящего с этого интерфейса, а не трафика, входящего с каких-либо других интерфейсов, таких как интерфейс WireGuard.
В качестве альтернативы мы могли бы использовать флаг -d 203.0.113.2 (с общедоступным IP-адресом общедоступного сервера) для получения аналогичного результата, сопоставляя трафик по исходному IP-адресу назначения, а не по входящему интерфейсу.
Если вы используете nftables вместо iptables на своем общедоступном сервере, вместо запуска указанной выше команды iptables для настройки переадресации портов вы должны добавить правило типа tcp dport 2000 dnat ip to 10.0.0.1:8080 в цепочку предварительной маршрутизации nat. в вашей конфигурации nftables. Ниже приведен полный пример файла конфигурации nftables, который делает это
Скрипт на случай использования nftables на сервере:
#!/usr/sbin/nft -f flush ruleset define pub_iface = "eth0" define wg_iface = "wg0" define wg_port = 51822 table inet filter { chain input { type filter hook input priority 0; policy drop; # accept all loopback packets iif "lo" accept # accept all icmp/icmpv6 packets meta l4proto { icmp, ipv6-icmp } accept # accept all packets that are part of an already-established connection ct state vmap { invalid : drop, established : accept, related : accept } # drop new connections over rate limit ct state new limit rate over 1/second burst 10 packets drop # accept all DHCPv6 packets received at a link-local address ip6 daddr fe80::/64 udp dport dhcpv6-client accept # accept all SSH packets received on a public interface iifname $pub_iface tcp dport ssh accept # accept all WireGuard packets received on a public interface iifname $pub_iface udp dport $wg_port accept # reject with polite "port unreachable" icmp response reject } chain forward { type filter hook forward priority 0; policy drop; # forward all packets that are part of an already-established connection ct state vmap { invalid : drop, established : accept, related : accept } # forward any incoming packets from a public interface that will go out through WireGuard iifname $pub_iface oifname $wg_iface accept # reject with polite "host unreachable" icmp response reject with icmpx type host-unreachable } } table inet nat { chain prerouting { type nat hook prerouting priority -100; policy accept; # rewrite destination address of TCP port 2000 packets to port 8080 on 10.0.0.1 iifname $pub_iface tcp dport 2000 dnat ip to 10.0.0.1:8080 } }
См. раздел «Точка-сайт с переадресацией портов» руководства по настройке WireGuard Nftables для получения полного объяснения этих правил брандмауэра.
Эта конфигурация предоставит вам базовое соединение между частным сервером и общедоступным сервером (проверьте это, запустив curl 10.0.0.1:8080 на общедоступном сервере — вы должны увидеть выходные данные веб-приложения на частном сервере). Однако он не позволит пересылать интернет-трафик между двумя серверами. Для этого вам необходимо добавить один из методов из следующих разделов.
Masquerading
Самый простой способ разрешить пересылку обратного трафика с частного сервера на общедоступный сервер — использовать SNAT (преобразование адресов исходной сети) на общедоступном сервере для преобразования исходного адреса пересылаемых пакетов для использования собственного IP-адреса общедоступного сервера. Когда SNAT используется таким образом, это называется «маскарадом» (в этом примере общедоступный сервер «маскирует» идентичность пакетов из Интернета своей собственной идентичностью).
Поскольку частный сервер получает эти пересылаемые пакеты с уже переписанным исходным адресом для использования IP-адреса WireGuard общедоступного сервера, на частном сервере не требуется вносить изменения в маршрутизацию — частный сервер знает, что может ответить на эти пакеты, отправляя трафик напрямую обратно. на общедоступный сервер. Брандмауэр общедоступного сервера запоминает исходные источники трафика и перезаписывает пункты назначения ответных пакетов обратно на исходные исходные IP-адреса.
Чтобы применить маскировку с помощью iptables, добавьте следующие команды PreUp и PostDown в файл конфигурации WireGuard общедоступного сервера:
# /etc/wireguard/wg0.conf # local settings for the public server [Interface] PrivateKey = ABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBFA= Address = 10.0.0.2 ListenPort = 51822 # packet forwarding PreUp = sysctl -w net.ipv4.ip_forward=1 # port forwarding PreUp = iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 2000 -j DNAT --to-destination 10.0.0.1:8080 PostDown = iptables -t nat -D PREROUTING -i eth0 -p tcp --dport 2000 -j DNAT --to-destination 10.0.0.1:8080 # packet masquerading PreUp = iptables -t nat -A POSTROUTING -o wg0 -j MASQUERADE PostDown = iptables -t nat -D POSTROUTING -o wg0 -j MASQUERADE # remote settings for the private server [Peer] PublicKey = /TOE4TKtAqVsePRVR+5AA43HkAK5DSntkOCO7nYq5xU= AllowedIPs = 10.0.0.1
Или, если вы используете nftables вместо iptables, добавьте следующую цепочку nat postrouting в файл конфигурации nftables публичного сервиса:
#!/usr/sbin/nft -f flush ruleset # ... table inet nat { chain prerouting { type nat hook prerouting priority -100; policy accept; # rewrite destination address of TCP port 2000 packets to port 8080 on 10.0.0.1 iifname $pub_iface tcp dport 2000 dnat ip to 10.0.0.1:8080 } chain postrouting { type nat hook postrouting priority 100; policy accept; # masquerade all packets going out through WireGuard oifname $wg_iface masquerade } }
Недостатком маскировки является то, что она скрывает исходный исходный IP-адрес клиентов, использующих веб-приложение, от самого веб-приложения — весь трафик, который получает частный сервер, будет использовать IP-адрес общедоступного сервера WireGuard (10.0.0.2) в качестве источника. Но теперь вы, по крайней мере, сможете подключиться к веб-приложению на частном сервере с любого устройства через Интернет, используя имя хоста и порт общедоступного сервера (например, Curl public.example.com:2000).
Static Routes
Если вы заранее знаете, что ваш интернет-трафик будет исходить только из нескольких статических диапазонов IP-адресов (например, 198.51.100.87 и диапазон от 192.0.2.144 до 192.0.2.147), другой вариант, который вы можете использовать, — это просто определить статические маршруты для этих IP-адресов на частном сервере, чтобы он всегда отправлял трафик обратно на эти IP-адреса через общедоступный сервер. Это тот же подход, который использовался в статье WireGuard Point to Site с переадресацией портов, где мы знаем, что весь трафик будет поступать из подсети сайта B (192.168.200.0/24 в этой статье).
Все, что вам нужно сделать в этом случае, — это добавить статические IP-адреса в настройку AllowedIPs в конфигурации WireGuard частного сервера:
# /etc/wireguard/wg0.conf # local settings for the private server [Interface] PrivateKey = AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEE= Address = 10.0.0.1 # remote settings for the public server [Peer] PublicKey = fE/wdxzl0klVp/IR8UcaoGUMjqaWi3jAd7KzHKFS6Ds= Endpoint = 203.0.113.2:51822 AllowedIPs = 10.0.0.2, 198.51.100.87, 192.0.2.144/30 PersistentKeepalive = 25
Сделав это, вы сможете подключиться к веб-приложению на частном сервере, используя имя и порт общедоступного сервера (например, curl public.example.com:2000) с любого хоста, который использует один из этих адресов AllowedIPs в качестве своего. общедоступный интернет-адрес (например, 192.0.2.145). Веб-приложение на частном сервере увидит исходный IP-адрес источника (например, 192.0.2.145), но по-прежнему сможет правильно отправлять ответы обратно через общедоступный сервер.
Маршрут по умолчанию
Если частному серверу на самом деле не нужен доступ к отдельной базе данных и очереди сообщений (или вместо этого он может получить к ним доступ через WireGuard), и вам на самом деле не нужно подключаться к частному серверу по SSH для администрирования (или если вы можете вместо SSH к нему через WireGuard), вы можете позволить WireGuard взять на себя маршрут по умолчанию частного сервера и по умолчанию отправлять весь его трафик через WireGuard на общедоступный сервер.
В этом случае вы просто установите для параметра AllowedIPs значение 0.0.0.0/0 в конфигурации WireGuard частного сервера:
# /etc/wireguard/wg0.conf # local settings for the private server [Interface] PrivateKey = AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEE= Address = 10.0.0.1 # remote settings for the public server [Peer] PublicKey = fE/wdxzl0klVp/IR8UcaoGUMjqaWi3jAd7KzHKFS6Ds= Endpoint = 203.0.113.2:51822 AllowedIPs = 0.0.0.0/0 PersistentKeepalive = 25
Если вы это сделаете, вы сможете подключиться к веб-приложению на частном сервере с любого хоста в Интернете, используя имя хоста и порт общедоступного сервера (например, curl public.example.com:2000). Веб-приложение на частном сервере будет видеть исходный IP-адрес источника и отправлять ответы (а также весь другой трафик) через соединение WireGuard на общедоступный сервер.
Маршрут по умолчанию с исключениями
Если вы заранее знаете, что внутренний трафик частного сервера ограничен всего несколькими подсетями, вы можете позволить WireGuard взять на себя маршрут по умолчанию частного сервера и добавить несколько статических маршрутов для вашего внутреннего трафика в качестве исключений. Это противоположность описанной выше опции «Статические маршруты» — вместо перечисления IP-адресов или диапазонов, которые вы всегда хотите отправлять через туннель WireGuard, вы перечисляете IP-адреса или диапазоны, которые вы никогда не хотите отправлять через туннель WireGuard.
Это идеально подходит для примера сценария, в котором база данных и очередь сообщений, используемые частным сервером, находятся в подсети 10.11.12.0/24, а доступ по SSH будет осуществляться только из подсети 192.168.99.0/24. В этом случае вы должны настроить конфигурацию WireGuard частного сервера на использование значения AllowedIPs 0.0.0.0/0 и добавить явные маршруты на частном сервере для этих внутренних сетей, что вы также можете сделать через файл конфигурации WireGuard:
# /etc/wireguard/wg0.conf # local settings for the private server [Interface] PrivateKey = AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEE= Address = 10.0.0.1 # static route for database and message queue PreUp = ip route add 10.11.12.0/24 via 192.168.1.1 dev eth0 PostDown = ip route del 10.11.12.0/24 via 192.168.1.1 dev eth0 # static route for SSH access PreUp = ip route add 192.168.99.0/24 via 192.168.1.1 dev eth0 PostDown = ip route del 192.168.99.0/24 via 192.168.1.1 dev eth0 # remote settings for the public server [Peer] PublicKey = fE/wdxzl0klVp/IR8UcaoGUMjqaWi3jAd7KzHKFS6Ds= Endpoint = 203.0.113.2:51822 AllowedIPs = 0.0.0.0/0 PersistentKeepalive = 25
Убедитесь, что вы используете фактический шлюз и сетевой интерфейс частного сервера по умолчанию вместо 192.168.1.1 и eth0. Вы можете определить шлюз сервера по умолчанию, выполнив команду ip Route — строка, начинающаяся с default, показывает шлюз по умолчанию:
$ ip route
default via 192.168.1.1 dev eth0 proto dhcp src 192.168.1.11 metric 100
192.168.1.0/24 dev eth0 proto kernel scope link src 192.168.1.11 metric 100
Если вы воспользуетесь этим подходом, вы сможете подключиться к веб-приложению на частном сервере с любого хоста в Интернете, используя имя хоста и порт общедоступного сервера (например, curl public.example.com:2000). Веб-приложение на частном сервере будет видеть исходный IP-адрес источника всего интернет-трафика, но по-прежнему сможет правильно отправлять ответы обратно через общедоступный сервер.
Policy Routing
Последний вариант — использовать маршрутизацию на основе политик. Это также очень хорошо подходит для примера сценария. Обычно маршрутизация политики с WireGuard используется путем объединения трех вещей:
Добавьте параметр «Таблица» в раздел [Интерфейс] вашей конфигурации WireGuard. Это предписывает wq-quick добавлять маршруты в пользовательскую таблицу вместо основной таблицы маршрутизации.
Добавьте свои пользовательские правила политики с помощью команды ip rule add, чтобы направить выбранный трафик на использование пользовательской таблицы.
Установите AllowedIPs = 0.0.0.0/0 для одного из узлов в вашей конфигурации WireGuard. Это гарантирует, что любой трафик, направленный на использование пользовательской таблицы маршрутизации (и не соответствующий разрешенным IP-адресам какого-либо другого узла), будет отправлен этому узлу.
Чтобы вернуть весь трафик на частном сервере, который первоначально вошел через его интерфейс WireGuard, обратно через тот же интерфейс, используйте это для конфигурации WireGuard частного сервера:
# /etc/wireguard/wg0.conf # local settings for the private server [Interface] PrivateKey = AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEE= Address = 10.0.0.1 Table = 123 PreUp = ip rule add from 10.0.0.1 table 123 priority 456 PostDown = ip rule del from 10.0.0.1 table 123 priority 456 # remote settings for the public server [Peer] PublicKey = fE/wdxzl0klVp/IR8UcaoGUMjqaWi3jAd7KzHKFS6Ds= Endpoint = 203.0.113.2:51822 AllowedIPs = 0.0.0.0/0 PersistentKeepalive = 25
Вышеупомянутое правило политики работает, поскольку обратный трафик будет использовать тот же IP-адрес в качестве источника своих обратных пакетов, что и исходные пакеты, используемые в качестве адреса назначения. Все адреса назначения пакетов, пересылаемых с общедоступного сервера на частный сервер, были преобразованы общедоступным сервером в 10.0.0.1; поэтому ответные пакеты, генерируемые частным сервером, будут использовать 10.0.0.1 в качестве адреса источника. Вышеупомянутое правило политики сопоставляет эти пакеты и гарантирует, что они маршрутизируются через пользовательскую таблицу маршрутизации 123; и wg-quick устанавливает маршрут по умолчанию для этой таблицы для использования интерфейса WireGuard.
CLI
$ echo '123 foo' | sudo tee -a /etc/iproute2/rt_tables
Затем вы можете ссылаться на таблицу 123 в конфигурации WireGuard как foo вместо 123:
Table = foo
PreUp = ip rule add from 10.0.0.1 table foo priority 456
PostDown = ip rule del from 10.0.0.1 table foo priority 456
При таком подходе вы сможете подключиться к веб-приложению на частном сервере с любого хоста в Интернете, используя имя хоста и порт общедоступного сервера (например, curl public.example.com:2000). Веб-приложение на частном сервере увидит исходный IP-адрес источника, но также сможет правильно отправлять ответы обратно через общедоступный сервер. Весь остальной трафик частного сервера, включая трафик, исходящий на самом частном сервере, будет продолжать использовать основную таблицу маршрутизации сервера, на которую не влияет ваша конфигурация WireGuard.
# free
Cпасибо автору!
Источник:
https://www.procustodibus.com/blog/2022/09/wireguard-port-forward-from-internet/