Браузер запитує https://203.0.113.10:8443, проксі приймає з’єднання, а служба на пірі WireGuard так і не відповідає. Правило DNAT робить свою роботу; збій відбувається у відповіді. Простежте пакет через обидва перетворення, і відсутнє правило стане очевидним. Виправлення — одна додаткова інструкція NAT у потрібному хуку, а не новий тунель.

Простежте один запит від початку до кінця

Запит надходить на публічний інтерфейс проксі, джерело — публічна адреса клієнта, призначення — адреса проксі. У nat PREROUTING правило DNAT перезаписує призначення на адресу тунелю піра, 10.90.0.2. Далі рішення маршрутизації надсилає пакет назовні через wg0, і шлях пересилання завершено.

На пірі пакет тепер несе початкову публічну адресу джерела, бо ніщо її не перезаписувало. Служба приймає з’єднання і надсилає відповідь на власний шлюз за замовчуванням — домашній маршрутизатор перед піром. У цього маршрутизатора немає стану для потоку, якого він ніколи не бачив, тож він або відкидає пакет, або транслює його на власну публічну адресу, чого клієнт не прийме.

Асиметрія і є вся проблема: запит іде через проксі, а відповідь намагається йти напряму. Відстеження з’єднань проксі допомагає, лише якщо відповідь повертається через проксі, а повернутися туди вона не може, поки адреса джерела вказує на початкового клієнта.

Додайте зворотне перетворення

Перезапишіть джерело потоку, що пересилається на адресу тунелю проксі, перш ніж він піде до піра. Тоді служба відповідає на 10.90.0.1, проксі отримує відповідь, і відстеження з’єднань обертає обидва перетворення, перш ніж пакет повернеться до клієнта.

iptables -t nat -A PREROUTING -p tcp -m multiport --dports 8080,8443 -j DNAT --to-destination 10.90.0.2
iptables -t nat -A POSTROUTING -d 10.90.0.2 -o wg0 -p tcp -m multiport --dports 8080,8443 -j SNAT --to-source 10.90.0.1

Правило POSTROUTING навмисно вузьке: воно збігається з трансльованим призначенням і інтерфейсом тунелю, тому не перезаписує сторонній трафік, що випадково виходить через wg0. Широке правило masquerade теж приховало б адресу клієнта, але зробило б це для кожного потоку і ускладнило б аудит таблиці NAT.

Розмістіть правила там, де існує тунель

Правила, що посилаються на адресу або інтерфейс тунелю, мають виконуватися після того, як wg-quick його налаштує. Інтерфейс створюється до PreUp, але адреси, MTU, DNS і маршрути застосовуються після, а PostUp запускається, коли все це на місці. Доповнення розмістіть у PostUp, а видалення — у PreDown.

PostUp = iptables -t nat -A PREROUTING -p tcp -m multiport --dports 8080,8443 -j DNAT --to-destination 10.90.0.2
PostUp = iptables -t nat -A POSTROUTING -d 10.90.0.2 -o wg0 -p tcp -m multiport --dports 8080,8443 -j SNAT --to-source 10.90.0.1
PreDown = iptables -t nat -D PREROUTING -p tcp -m multiport --dports 8080,8443 -j DNAT --to-destination 10.90.0.2
PreDown = iptables -t nat -D POSTROUTING -d 10.90.0.2 -o wg0 -p tcp -m multiport --dports 8080,8443 -j SNAT --to-source 10.90.0.1

Видалення мають збігатися з доповненнями токен у токен, включно зі збігами multiport та інтерфейсу. Видалення, що відрізняється на один збіг, нічого не видаляє, а наступне перепідключення додає другу копію правила. Після кількох перепідключень у таблиці з’являються дублікати, які важко прив’язати до рядка конфігурації.

Перевірте результат за допомогою iptables -t nat -S після перепідключення. Якщо те саме правило з’являється двічі, рядок PreDown не збігається, і очищення мовчки не працює.

Пересилання, фільтрація та інший NAT

Увімкніть пересилання IPv4 постійно, потім дозвольте пересиланий потік у таблиці фільтра. DNAT відбувається до ланцюжка FORWARD, тому правило фільтра збігається з трансльованим призначенням, а не з публічною адресою. Якщо UFW керує брандмауером, висловіть дозвіл як правило маршруту; звичайне правило хоста не покриває пересиланий трафік.

Ще два рівні NAT можуть зламати шлях, навіть коли правила проксі правильні. При домашньому підключенні публічна адреса належить маршрутизатору, і відкриття порту в його брандмауері — не те саме, що створення запису пробросу порту, який надсилає цей порт на проксі. Порт, який зовні виглядає відкритим, хоча ніщо не відповідає, часто позбавлений саме цього зіставлення.

На VPS з NAT провайдер зіставляє публічний порт із приватною адресою. Зіставлення має збігатися з оголошуваним портом, а невідповідність виглядає так само, як зламаний тунель. Підтвердьте зіставлення у провайдера, перш ніж змінювати конфігурацію WireGuard.

Перевірте зворотний шлях і прийміть ціну

Підключіться з мережі, яка не є LAN проксі, потім огляньте пару перетворень, поки з’єднання відкрите:

conntrack -L -p tcp --dport 8080
tcpdump -ni any tcp port 8080

Запис conntrack має показувати початковий кортеж, трансльований кортеж і напрямок відповіді. Якщо відповідь відсутня, пір не надсилає через тунель, що зазвичай означає, що правило SNAT не застосувалося або власний брандмауер піра відкинув потік.

Перезавантажтеся один раз, щоб довести, що PostUp знову застосовує правила, потім зупиніть тунель і підтвердьте, що PreDown їх видалив. Мертві правила, які переживають відключення, — причина того, що подальша зміна поводиться непередбачувано.

Нарешті, прийміть ціну SNAT. Служба бачить кожен запит як такий, що прийшов від проксі, тому журнали доступу, обмеження швидкості на клієнта і списки дозволених адрес більше не розрізняють користувачів. Випадку hairpin потрібне власне перетворення джерела для клієнтів у LAN проксі. Якщо піру потрібні справжні адреси клієнтів, альтернатива — зворотний маршрут до мережі клієнта, це більше роботи, але зберігає інформацію.

Схожі статті