Вопрос или проблема
—
Введение
Здравствуйте,
Я работаю с настройкой Docker-Compose, которая запускает как WireGuard, так и CoreDNS, и моя цель заключается в том, чтобы CoreDNS записывал фактические IP-адреса клиентских пиров, отключив NAT. Эта часть достаточно проста и не является проблемой, но из-за сегментации сети все стало очень сложно. Поскольку я не специалист по сетям и знаю только основы, устранение этой проблемы оказалось весьма сложной задачей.
Настройка Docker-Compose
Вот мой текущий docker-compose.yml
:
version: '3.3'
services:
wireguard:
image: lscr.io/linuxserver/wireguard:latest
container_name: wireguard
restart: unless-stopped
cap_add:
- NET_ADMIN
sysctls:
- net.ipv4.conf.all.src_valid_mark=1
environment:
- PUID=1000
- PGID=1000
- TZ=Etc/UTC
- SERVERURL=***
- SERVERPORT=51820
- PEERS=1
- PEERDNS=172.29.0.3
- INTERNAL_SUBNET=10.13.13.0
- ALLOWEDIPS=0.0.0.0/0
- LOG_CONFS=true
ports:
- "51820:51820/udp"
volumes:
- /root/volumes/wireguard/config:/config
networks:
vpn_net:
ipv4_address: 172.28.0.2
dns_net:
ipv4_address: 172.29.0.2
coredns:
image: coredns:latest
container_name: coredns
volumes:
- /root/volumes/coredns/Corefile:/Corefile
- /etc/letsencrypt/live/***.com/fullchain.pem:/fullchain.pem:ro
- /etc/letsencrypt/live/***.com/privkey.pem:/privkey.pem:ro
cap_add:
- NET_ADMIN
networks:
dns_net:
ipv4_address: 172.29.0.3
command: ["-conf", "Corefile"]
networks:
vpn_net:
driver: bridge
ipam:
config:
- subnet: 172.28.0.0/16
dns_net:
driver: bridge
ipam:
config:
- subnet: 172.29.0.0/16
Docker-compose раскрывает архитектуру сети:
- WireGuard: vpn_net, dns_net
- CoreDNS: dns_net
Конфигурация WireGuard настраивается автоматически, и все работает как ожидалось. Контейнер CoreDNS доступен (ping 172.29.0.3
).
На этом этапе активна стандартная сгенерированная конфигурация WireGuard, которая включает NAT. В этом случае CoreDNS легко доступен, и dig google.de @172.29.0.3
возвращает ответ.
Внутри VPN-туннеля я могу достичь CoreDNS, пока включен NAT.
Конфигурация без NAT
Однако, поскольку CoreDNS записывает IP контейнера вместо IP клиента, я хочу отключить NAT. Это можно легко сделать в конфигурации WireGuard. Директивы PostUp и PostDown устанавливают правильные правила iptables при запуске сервера:
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 ! -d 172.29.0.0/16 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 ! -d 172.29.0.0/16 -j MASQUERADE
Все кажется в порядке. Однако, когда я выполняю ping до CoreDNS изнутри VPN-туннеля (ping 172.29.0.3
), я получаю тайм-аут. Интересно, что когда я запускаю dig google.de @172.29.0.3
, CoreDNS регистрирует DNS-запрос с IP клиента 10.13.13.x
… Это означает, что трафик успешно достигает контейнера CoreDNS, но не маршрутизируется обратно. В стандартной настройке WireGuard (где NAT активен) это работает идеально. Для меня совершенно неясно, почему это не работает.
Попытки устранения неполадок
Я пробовал множество решений более 20 часов, но безуспешно. Внутри контейнера CoreDNS я добавил следующий маршрут:
ip route add 10.13.13.0/24 via 172.29.0.2
Но это не работает.
Я могу запустить dig google.de @172.29.0.3
, и CoreDNS регистрирует запрос, но я не получаю ответ.
Тот факт, что CoreDNS регистрирует запрос, указывает, что трафик успешно передается от WireGuard к CoreDNS. Однако кажется, что трафик не маршрутизируется обратно к WireGuard.
Запрос о помощи
Я действительно застрял на этом моменте. Может быть, какие-то эксперты по сетям смогут помочь мне понять топологию и определить, где, вероятно, застревает трафик.
Может быть, какие-то сетевые гики смогут углубиться в топологию и отследить, как движется трафик, чтобы выяснить, где он, вероятно, застревает.
Для меня это важный проект на основе увлечения, и я вкладываю все усилия в решение этой проблемы. Я должен найти решение, иного пути нет. Весь мой проект зависит от этого, и он много значит для меня.
Заранее спасибо, желаю вам всего наилучшего и хорошего дня!
Ответ или решение
Решение задачи маршрутизации при использовании WireGuard и Docker для сохранения реальных IP-адресов клиентов без применения NAT может показаться сложным из-за специфики сетевой настройки и маршрутизации пакетов между контейнерами Docker. Обратим внимание на ключевые элементы этой задачи и потенциальные методы её решения.
Теория
Сетевые технологии, такие как Docker и VPN, например, WireGuard, требуют понимания нескольких ключевых аспектов. Docker использует свои собственные сетевые драйверы для изоляции контейнеров и их взаимодействия. Ваша установка включает два таких моста – vpn_net
и dns_net
, каждый из которых имеет свою подсеть. Ваше стремление отключить NAT в конфигурации WireGuard обусловлено желанием, чтобы CoreDNS мог логировать реальные IP-адреса клиентов, а не IP-адреса контейнеров. Однако отключение NAT приводит к проблемам с маршрутизацией возвратного трафика.
Когда NAT включен, запросы от клиентов, проходя через WireGuard, получают замещённый источником IP-адрес, принадлежащий контейнеру WireGuard. Таким образом, все ответы от CoreDNS автоматически возвращаются в этот контейнер, и он перенаправляет их к клиентам, что не вызывает проблем с маршрутизацией. Без NAT запросы от клиентов сохраняют свои исходные IP-адреса, и если не продуманы правила маршрутизации для возвратных пакетов, CoreDNS не сможет направить их обратно к клиенту через WireGuard.
Пример
Вы столкнулись с ситуацией, когда CoreDNS получает DNS-запросы и логирует их с клиентскими адресами в диапазоне 10.13.13.x
, но ответы не возвращаются к клиентам. Это классический пример асимметричной маршрутизации, где запрос достигает сервера, но ответ не может вернуться к отправителю. Подключение iptables в цепочке OUTPUT или POSTROUTING в CoreDNS для пометки пакетов маршрутной информацией — один из способов решения, но требует внимания к деталям конфигурации межсетевого экрана и маршрутизации пакетов.
Применение
Для решения вашей проблемы можно рассмотреть несколько шагов и подходов:
-
Обновление конфигурации маршрутизации:
- Удостоверьтесь, что в CoreDNS или соответствующем сетевом устройстве маршрутизация располагает информацией о сети клиента (
10.13.13.0/24
). Подключение маршрута через172.29.0.2
— шаг в правильном направлении, но это может быть не единственное изменение, необходимое для надлежащей маршрутизации. - Проверьте общий путь маршрутизации в системе через команду
traceroute
иtcpdump
, чтобы удостовериться, что возвратный маршрут до клиентского IP имеется и соблюдается.
- Удостоверьтесь, что в CoreDNS или соответствующем сетевом устройстве маршрутизация располагает информацией о сети клиента (
-
Использование политики маршрутизации:
- Добавление политик маршрутизации (Policy-Based Routing) может помочь направить трафик из CoreDNS в VPN-клиенты, в частности, при указании в роутинговых таблицах направлений боле сложной логики маршрута.
-
Правила iptables:
- Измените правила iptables на сервере WireGuard и/или в контейнере CoreDNS. В частности, убедитесь, что все цепочки правил (FORWARD, OUTPUT и т.п.) разрешают нужный трафик. Можно также рассмотреть добавление SNAT правил.
-
Обновление системной конфигурации контейнера:
- В зависимости от конфигурации сети, настройка IP Forwarding (
sysctl -w net.ipv4.ip_forward=1
) может быть необходимой как в Docker-хосте, так и внутри контейнеров.
- В зависимости от конфигурации сети, настройка IP Forwarding (
-
Просмотр логов и диагностика:
- Анализируйте логи Docker, WireGuard и CoreDNS для поиска вероятных ошибок конфигурации или сетевых проблем.
Комплексное понимание конфигурации сети Docker и ее ограничения, а также правильная установка маршрутизации, позволят устранить текущие проблемы и сохранить действительный клиентский IP. Это не быстрый процесс, но систематический подход позволит вам со временем прийти к оптимальному решению. Успехов!