Вопрос или проблема
Я пытаюсь настроить “простой” VPN между двумя Linux-машинами, используя Wireguard. К сожалению, существующие руководства, которые я нашел, не были настолько полезными, потому что они обычно A) настраивают только IPv4 и B) обычно используют IP-маскарадинг…
Конфигурация машины A:
[Interface]
Address = 192.168.10.2/24
ListenPort = 51820
[Peer]
AllowedIPs = 192.168.10.0/24, 172.16.0.0/24, fdbb:bbbb:bbbb::/48, 2001:db8:bbbb:0000::/64
Endpoint = [2001:db8:bbbb:0000:1234:56ff:fe78:90ab]:51820
PersistentKeepalive = 20
Конфигурация машины B:
[Interface]
Address = 192.168.10.1/24
ListenPort = 51820
[Peer]
AllowedIPs = 192.168.10.2/32, 10.0.0.0/16, fdaa:aaaa:aaaa::/48, 2001:db8:aaaa:0000::/64
Endpoint = [2001:db8:aaaa:0000:ba09:87ff:fe65:4321]:51820
PersistentKeepalive = 20
(Не указываю ключи, потому что туннель сам по себе передает трафик, так что я знаю, что они верны).
Итак, простая конфигурация, в теории. Машина A не имеет локального фаервола (только обычный потребительский маршрутизатор с встроенным фаерволом, с открытым UDP/51820), машина B имеет ip(6)tables, но только для всех правил Docker, и политики по умолчанию установлены на Принять.
Обе машины имеют net.ipv4.ip_forward=1
и net.ipv6.conf.all.forwarding=2
.
Эта конфигурация не работала, потому что Wireguard, видимо, пытается маршрутизировать собственный трафик wireguard через сам туннель, потому что IPv6 конечной точки включен в сеть AllowedIPs. Почему бы это не исключать по умолчанию…
Я попытался обойти это, добавив фиксированный маршрут для отправки трафика для этой конечной точки через обычный интерфейс, а не wg0:
PostUp = /usr/sbin/ip -6 route add 2001:db8:aaaa:0000:ba09:87ff:fe65:4321/128 via fe80::1 dev enp1s0
PreDown = /usr/sbin/ip -6 route del 2001:db8:aaaa:0000:ba09:87ff:fe65:4321/128 via fe80::1 dev enp1s0
С этой настройкой (с обеих сторон) узлы могут пинговать друг друга A) через адреса WG узла (192.168.10.X), B) через свои локальные IPv4 адреса (10.0.X.X или 172.16.X.X), и C) через свои ULA адреса.
Однако у меня все еще есть две проблемы с моим туннелем:
A) Поскольку мне пришлось добавить этот маршрут IPv6 к конечной точке, это означает, что трафик к публичному IPv6-адресу другого узла не проходит через туннель WG, а путешествует напрямую через интернет. Узлы не могут пинговать друг друга, используя свои публичные GUA-адреса IPv6. Мне нужно что-то вроде этого IP-маршрута, который я добавил с использованием параметра PostUp, но для того, чтобы это применялось только к самому туннелю, а не для трафика, проходящего через туннель. Как IPv6-маршрут, где я могу сказать “маршрутизировать UDP/51820 через этот маршрут (напрямую к интернету), но другой трафик к тому же IP через этот маршрут (wg0)”.
B) Я не могу заставить все работать с других машин в моей сети (по IPv4). На другой машине в сети A, я добавил статический маршрут к IPv4 другой сети: 172.16.0.0/24 via 10.0.1.25 dev enp7s0 metric 100
.
Когда я сейчас делаю traceroute, первый прыжок – это машина wireguard (10.0.1.25), и второй прыжок – это адрес узла WG удаленной машины (192.168.10.1) (так что он проходит через туннель!), но после этого – всё, нет третьего прыжка с фактическим адресатом (несмотря на то, что у шлюза по умолчанию на другой стороне есть статический маршрут для маршрутизации 10.0.0.0/8 на машину wireguard этой стороны. Я не хочу делать IP-маскарадинг, который является “решением”, которое я нашел много раз, используя Google. Я хочу, чтобы другие машины в другой сети точно видели, откуда идут запросы – машина на другой стороне туннеля.
По IPv6, с использованием ULAs, все нормально. Добавил маршрут IPv6 на шлюзе, чтобы маршрутизировать ULAs другой стороны к машине wireguard, и готово. Мне просто нужно найти решение для GUAs, вероятно, с radvd на машине wireguard, объявляющей маршрут к этой сети.
Краткое резюме: Соединение Wireguard между двумя узлами работает, но A) как отправить не-Wireguard трафик на IP конечной точки wireguard через туннель, и B) почему маршрутизация IPv6 ULA работает, а маршрутизация IPv4 не работает, хотя они настроены одинаково.
Мне удалось заставить это работать, используя IP правила, используя эти команды в конфигурации wireguard:
PostUp = ip -6 rule add to 2001:db8:aaaa::ba09:87ff:fe65:4321/128 ipproto udp dport 51820 table 200
PostUp = ip -6 route add default via fe80::1 dev eth0 table 200
PreDown = ip -6 rule del lookup 200
PreDown = ip -6 route del default via fe80::1 dev eth0 table 200
Это добавляет абсолютно отдельную таблицу маршрутизации 200
с единственным (по умолчанию) маршрутом для отправки всего трафика на локальный маршрутизатор, и затем он добавляет IP правило, чтобы любой UDP трафик на IPv6 конечной точки на порту 51820 обрабатывался согласно этой новой таблице маршрутизации.
Таким образом, UDP трафик для самого туннеля WG пойдет на маршрутизатор, но любые другие пакеты с тем же IP назначения пойдут через туннель WG.
И затем я просто добавил radvd с обеих сторон туннеля, объявив маршрут к префиксу GUA другой стороны, чтобы устройства в сети отправляли трафик на машину wireguard.
Ответ или решение
Конфигурация WireGuard для маршрутизации IPv4 и IPv6 может быть сложной задачей, особенно если учесть, что многие руководства фокусируются только на одном из этих протоколов или предполагают использование IP-маскарадинга, что не всегда подходит для более сложных сетевых сред. Пример, приведенный в описании проблемы, иллюстрирует частые трудности и ошибки, которые могут возникнуть при настройке сети WireGuard. Давайте разберем теоретическую основу проблемы, предложим примеры ее решения и рассмотрим их применение на практике.
Теория
WireGuard — это современный VPN-протокол, который обеспечивает безопасное туннелирование данных между узлами. Он функционирует на уровне сетевого интерфейса и требует настройки интерфейсов на обоих концах туннеля. Конфигурации, описанные для машин A и B, включают как IPv4, так и IPv6 адреса, что требует двойной настройки маршрутизации. Проблема в том, что если адресация и маршрутизация не установлены корректно, интерфейсы WireGuard могут пытаться перенаправить свой трафик через собственный туннель, что приводит к непредвиденным результатам.
Пример
В приведенном примере проблема заключалась в том, что IP-адреса конечных точек IPv6 были включены в список разрешенных IP-адресов (AllowedIPs), что приводило WireGuard к попытке маршрутизировать собственный трафик туннеля через туннель. Решение состояло в использовании команды PostUp для настройки маршрутов, чтобы определить, как различные типы трафика должны направляться через сеть. В данной конфигурации PostUp добавляет правило, которое направляет все UDP-пакеты, предназначенные для WireGuard, через маршрутизатор, а не через туннель.
Применение
Для решения проблемы были установлены вторичные правила маршрутизации, что позволяет разграничивать маршрутизацию UDP-пакетов, предназначенных для туннеля, и остальных пакетов. Создание отдельной таблицы маршрутизации и использование IP-правил для направления трафика в соответствии с протоколами и портами позволяет избежать круговой маршрутизации. Таким образом, можно задать маршрут для UDP-трафика WireGuard в обход туннеля, удерживая остальные пакеты сети в заданной маршрутизации через туннель.
Кроме того, настройка radvd (Router Advertisement Daemon) на обоих концах для объявления маршрутов к глобальному сетевому префиксу (GUA) позволяет устройствам в сети узнавать о доступных маршрутных путях через WireGuard. Это особенно полезно в IPv6-средах, поскольку позволяет автоматически обнаруживать и настраивать маршруты.
Выводы и рекомендации
В целях комплексной конфигурации VPN-сетей с поддержкой как IPv4, так и IPv6, необходимо предусмотреть следующие моменты:
- Изоляция трафика протокола WireGuard от остального трафика путем тщательной настройки таблиц маршрутизации и применения IP-правил.
- Проверка маршрутизации в сетях IPv6 с использованием инструментов как
radvd
для автоматического объявления маршрутов, упрощающего сетевую организацию. - Отказ от маскарадинга, если нужно сохранить видимость источника пакетов на конечной стороне туннеля, что требует тщательной настройки всех соответствующих маршрутов и маршрутизаторов.
- И, наконец, проверка всех брандмауэров и их правил на предмет блокировки трафика и обеспечения того, чтобы разрешения совпадали с желаемыми путями.
Эти шаги помогут не только решить конкретные проблемы, описанные выше, но и обеспечат более стабильную и надежную эксплуатацию WireGuard VPN для сложных сетевых сценариев с поддержкой обеих версий IP-протоколов.