WireGuard DNS DNAT: houd het antwoordpad werkend
DNAT herschrijft de bestemming, niet de bron. Bepaal hoe de upstream-resolver kan antwoorden voordat je de regel toevoegt, en houd elke overeenkomst nauw begrensd.
De DNS-query van een WireGuard-client naar een andere resolver sturen lijkt op één regel en gedraagt zich als drie beslissingen. De bestemming moet worden herschreven, het pakket moet worden doorgestuurd, en het antwoord moet zijn weg terug vinden door de vertaalstatus die de gateway heeft gemaakt. Sla de derde over en de query vertrekt netjes terwijl de client voor altijd wacht.
Neem het voorbeeld van geautoriseerde clients in 10.77.0.0/24 die via wg0 binnenkomen, het aangekondigde adres 10.77.0.1 opvragen en een resolver op 203.0.113.53 nodig hebben. Het upstream-adres is een plaatsaanduiding voor documentatie, geen werkende dienst.
Een query omleiden verandert alleen de bestemming
Een bestemmings-NAT-regel in PREROUTING herschrijft het adres voordat de routeringsbeslissing wordt genomen, dus het pakket wordt daarna naar de nieuwe bestemming gerouteerd in plaats van de oude. Het bronadres van de client blijft onaangetast door die bewerking. Daarom kan een regel die compleet lijkt toch stilte opleveren: het verzoek reist nu naar een resolver die nog nooit van het privébereik van de client heeft gehoord. De gateway vertaalde één veld en erfde een tweede probleem.
Beide DNS-transporten hebben bijpassende regels nodig, omdat een client terugvalt op TCP wanneer een antwoord wordt afgekapt.
De regels hieronder selecteren één inkomende interface, één clientbereik en één oorspronkelijk bestemmingsadres. Niets anders op de gateway wordt beïnvloed, en een query van de gateway zelf komt helemaal niet overeen.
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
Het antwoordpad is een aparte beslissing
Twee opstellingen laten het antwoord terugkeren, en vroeg één kiezen bespaart een debugsessie. Ofwel heeft de upstream-resolver een route terug naar 10.77.0.0/24 via deze gateway, ofwel vertaalt de gateway de bron bij het verlaten zodat het antwoord aankomt op een adres dat de upstream al kent. Beide werken; slechts één past bij de controle die je over de upstream hebt.
Routering verdient de eerste poging, omdat het het adres van de client zichtbaar houdt voor de resolver en een tweede vertaallaag vermijdt. Wanneer de upstream buiten je controle valt, is bronvertaling op de specifieke uitgaande interface de praktische keuze.
Beperk die vertaling net zo strikt als de omleiding, anders wordt de regel een algemene NAT voor alles wat er toevallig bij past:
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
Verbindingsregistratie houdt de mapping gepaard, zodat het antwoord op de terugweg weer naar de oorspronkelijke tuple van de client wordt herschreven. Zonder de uitgaande regel stuurt de resolver zijn antwoord naar een privéadres dat hij niet kan bereiken, en de client ziet een time-out in plaats van een fout.
Schrijf de regels smaller dan de taak lijkt
Doorstuurtoestemming hoort bij dezelfde scope. Sta de stroom van client naar resolver toe en het retourverkeer dat conntrack al herkent, in plaats van elke DNAT-verbinding op de machine te accepteren. Een blanket-acceptatie machtigt ook poortdoorschakelingen die niets met DNS te maken hebben.
De eigen resolver van de gateway is een ander codepad. Een lokaal uitgegeven query gaat door OUTPUT, dus testen vanuit de gateway-shell oefent noch de PREROUTING-regel noch het doorstuurbeleid. Daarom kan een lokale test slagen terwijl elke client faalt, en het omgekeerde is even gewoon.
Niets hier dekt DNS over HTTPS op poort 443 of DNS over TLS op poort 853, en niets dekt IPv6. Een client met een geconfigureerde IPv6-resolver negeert de hele opstelling met plezier.
Wat een verse query bewijst
Verbindingsregistratie onthoudt eerdere mappings, dus een query die vóór een regelwijziging is verzonden kan uit de oude toestand worden beantwoord en de nieuwe regel stuk lijken. Begin met een nieuwe bronpoort en, waar de client antwoorden cachet, met een nieuwe naam.
dig @10.77.0.1 example.com A +short
conntrack -L -p udp --dport 53 | head
De eerste opdracht toont of het clientpad überhaupt oplost, en de tweede toont de vertaling die de gateway werkelijk heeft geïnstalleerd, inclusief beide richtingen van de tuple. Een mapping die naar de juiste resolver wijst met een antwoordteller die op nul blijft steken is een probleem met het terugpad en niet met filteren.
Bevestig dat de resolver de namen kent die je verwacht voordat je iets omleidt. Een vervanging die openbare namen beantwoordt maar niet je privézone verandert een werkende opzoeking in een NXDOMAIN dat op een kapotte tunnel lijkt. Test de resolver rechtstreeks, vanaf de gateway, voordat het clientpad erbij betrokken is. En de referentie voor iptables-uitbreidingen documenteert de DNAT- en masquerade-semantiek waarop deze regels berusten.