Спрямування DNS-запиту клієнта WireGuard на інший resolver виглядає як одне правило, а поводиться як три рішення. Призначення треба переписати, пакет треба передати, а відповідь має знайти шлях назад через стан трансляції, створений шлюзом. Пропустіть третє — і запит чисто піде, поки клієнт чекає вічно.

Візьміть приклад: авторизовані клієнти в 10.77.0.0/24 приходять через wg0, запитують оголошену адресу 10.77.0.1 і потребують resolver за адресою 203.0.113.53. Вищерозташована адреса — це заглушка для документації, а не робочий сервіс.

Перенаправлення запиту змінює лише його призначення

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

Обидва транспорти DNS потребують відповідних правил, бо клієнт повертається до TCP, коли відповідь усікається.

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

sysctl -w net.ipv4.ip_forward=1
iptables -t nat -A PREROUTING -i wg0 -s 10.77.0.0/24 -d 10.77.0.1 -p udp --dport 53 -j DNAT --to-destination 203.0.113.53:53
iptables -t nat -A PREROUTING -i wg0 -s 10.77.0.0/24 -d 10.77.0.1 -p tcp --dport 53 -j DNAT --to-destination 203.0.113.53:53

Зворотний шлях — окреме рішення

Дві схеми дозволяють відповіді повернутися, і ранній вибір однієї економить сеанс налагодження. Або у вищерозташованого resolver є маршрут назад до 10.77.0.0/24 через цей шлюз, або шлюз транслює джерело на виході, щоб відповідь надійшла на адресу, яку вища сторона вже знає. Працюють обидві; лише одна відповідає рівню контролю, який ви маєте над вищою стороною.

Маршрутизація заслуговує першої спроби, бо вона зберігає адресу клієнта видимою для resolver і уникає другого шару трансляції. Коли вища сторона поза вашим контролем, трансляція джерела на конкретному вихідному інтерфейсі — практичний вибір.

Обмежте цю трансляцію так само вузько, як перенаправлення, інакше правило стане NAT загального призначення для всього, що випадково з ним збігається:

iptables -t nat -A POSTROUTING -s 10.77.0.0/24 -d 203.0.113.53 -o eth0 -p udp --dport 53 -j MASQUERADE
iptables -t nat -A POSTROUTING -s 10.77.0.0/24 -d 203.0.113.53 -o eth0 -p tcp --dport 53 -j MASQUERADE

Відстеження з'єднань тримає відображення в парі, тому відповідь переписується назад у початковий tuple клієнта на зворотному шляху. Без вихідного правила resolver надсилає відповідь на приватну адресу, до якої не може дістатися, і клієнт бачить тайм-аут замість помилки.

Пишіть правила вужче, ніж виглядає завдання

Дозвіл на пересилання належить до тієї самої області. Дозвольте потік від клієнта до resolver і зворотний трафік, який conntrack уже розпізнає, замість того щоб приймати кожне з'єднання DNAT на машині. Суцільний дозвіл також санкціонує переадресацію портів, що не має відношення до DNS.

Власний resolver шлюзу — це інший шлях коду. Запит, виданий локально, проходить через OUTPUT, тому тестування з оболонки шлюзу не вправляє ні правило PREROUTING, ні політику пересилання. Ось чому локальний тест може пройти, поки кожен клієнт зазнає невдачі, і навпаки так само часто.

Тут ніщо не охоплює DNS поверх HTTPS на порту 443 або DNS поверх TLS на порту 853, і ніщо не охоплює IPv6. Клієнт із налаштованим resolver IPv6 із задоволенням проігнорує всю схему.

Що доводить свіжий запит

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

dig @10.77.0.1 example.com A +short
conntrack -L -p udp --dport 53 | head

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

Перш ніж щось перенаправляти, переконайтеся, що resolver знає очікувані імена. Заміна, яка відповідає на публічні імена, але не на вашу приватну зону перетворює робочий пошук на NXDOMAIN, який виглядає як зламаний тунель. Перевірте resolver напряму, зі шлюзу, перш ніж буде задіяний шлях клієнта. А довідник з розширень iptables описує семантику DNAT і masquerade, на яку спираються ці правила.

Схожі статті