Насочването на DNS заявка от клиент на WireGuard към друг резолвер изглежда като едно правило, но се държи като три решения. Дестинацията трябва да бъде пренаписана, пакетът трябва да бъде препратен, а отговорът трябва да намери пътя обратно през състоянието на транслация, което шлюзът е създал. Пропуснете третото и заявката излиза чисто, докато клиентът чака вечно.

Вземете примера с оторизирани клиенти в 10.77.0.0/24, идващи през wg0, питащи обявения адрес 10.77.0.1 и нуждаещи се от резолвер на 203.0.113.53. Горният адрес е документационен заместител, а не работеща услуга.

Пренасочването на заявка променя само нейната дестинация

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

И двата 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

Пътят на отговора е отделно решение

Две подредби позволяват отговорът да се върне и изборът на една от тях рано спестява сесия за отстраняване на грешки. Или горният резолвер има маршрут обратно към 10.77.0.0/24 през този шлюз, или шлюзът превежда източника на изхода, така че отговорът да пристигне на адрес, който горната страна вече познава. И двете работят; само едното съответства на контрола, който имате върху горната страна.

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

Ограничете тази транслация толкова тясно, колкото пренасочването, иначе правилото се превръща в 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

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

Пишете правилата по-тесни, отколкото изглежда задачата

Разрешението за препращане принадлежи към същия обхват. Разрешете потока от клиент към резолвер и обратния трафик, който conntrack вече разпознава, вместо да приемате всяка DNAT връзка на машината. Цялостното приемане също разрешава пренасочвания на портове, които нямат нищо общо с DNS.

Собственият резолвер на шлюза е различен кодови път. Заявка, издадена локално, минава през OUTPUT, така че тестването от шела на шлюза не упражнява нито правилото PREROUTING, нито политиката за препращане. Ето защо локален тест може да мине, докато всеки клиент се проваля, а обратното е също толкова често.

Тук нищо не покрива DNS през HTTPS на порт 443 или DNS през TLS на порт 853 и нищо не покрива IPv6. Клиент с конфигуриран IPv6 резолвер ще игнорира цялата подредба с удоволствие.

Какво доказва свежата заявка

Проследяването на връзки помни по-ранни картографирания, така че заявка, изпратена преди промяна на правилото, може да бъде отговорена от старото състояние и да накара новото правило да изглежда счупено. Започнете с нов порт на източника и, където клиентът кешира отговори, с ново име.

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

Първата команда показва дали пътят на клиента изобщо се решава, а втората показва транслацията, която шлюзът действително е инсталирал, включително двете посоки на кортежа. Картографиране, сочещо към правилния резолвер, с брояч на отговорите, заседнал на нула, е проблем с пътя на връщане, а не с филтрирането.

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

Подобни статии