De tunnel is actief, de firewall staat poort 53 toe, AdGuard Home draait, en namen worden nog steeds niet opgelost voor de WireGuard-client. De query komt normaal aan en een antwoord vertrekt normaal, dus de pakket-tellers op de resolver zien er gezond uit en de dienst lijkt onschuldig. Wat misgaat is het bronadres op dat antwoord: het vertrekt vanaf een lokaal adres dat de client nooit heeft gevraagd, en de stub-resolver van de client gooit het weg. Eén lijst in de configuratie van AdGuard Home bepaalt dit, en het gebruikelijke standaardgedrag geeft de beslissing door aan de kernel.

De query komt aan, het antwoord vertrekt vanaf een andere plek

Een client die 10.6.0.1 als resolver heeft geconfigureerd, verstuurt een UDP-query naar 10.6.0.1 poort 53. Dat pakket gaat door de tunnel en komt op de host aan, en AdGuard Home beantwoordt het. Op het netwerk is het antwoord echter een nieuw pakket waarvan het bronadres wordt gekozen door de stack van de host, niet door de verwachting van de client.

Wanneer de resolver van de client een verbonden socket is, wat wordt gebruikt door systemd-resolved, dnsmasq en de meeste stub-resolvers, accepteert deze alleen antwoorden van het exacte adres waarnaar het query is gestuurd. Een antwoord afkomstig van 192.168.1.10 op een query verzonden naar 10.6.0.1 wordt weggegooid voordat er enige parsing plaatsvindt. De resolver logt een succesvol antwoord, de client logt een time-out, en beide vertellen de waarheid.

Dus de tellers liegen niet en de klant ook niet. Het bewijs dat je nodig hebt bevindt zich op drie plaatsen, in deze volgorde: het adres waaraan de luisteraar is gebonden, de route die de kernel zou gebruiken terug naar de klant, en het bronadres op het daadwerkelijke antwoordpakket.

Hoe de kernel de bron van het antwoord kiest

Een UDP-socket gebonden aan0.0.0.0heeft geen eigen bronadres, dus elke uitgaande reactie veroorzaakt een route-opzoeking voor de bestemming. De kernel neemt vervolgens de bron van die route: het door de route gekoppelde adres, of het primaire adres van de uitgaande interface. Er wordt niets onthouden over het bestemmingsadres van de query.

Op een single-homed host is dit onzichtbaar, omdat er maar één plausibel antwoord is. Op een machine met een LAN-adres, een WireGuard-adres en een beheersadres zijn verschillende antwoorden plausibel, en de winnaar hangt af van de routingtabel op dat moment. Voeg een extra route toe, een tweede adres op dezelfde interface, een NAT-omleiding voor de resolver, of draai AdGuard in een container met zijn eigen namespace, en de gekozen bron kan verschillen van degene die de cliënt heeft opgevraagd.

ss -lunp | grep :53geeft aan in welk spel je zit. Een listener op0.0.0.0:53is het wildcard-geval; een listener op10.6.0.1:53heeft het antwoord al vastgepind. Het lezen van de socket gaat sneller dan het lezen van de YAML, en het weerspiegelt wat er daadwerkelijk draait in plaats van wat voor het laatst is opgeslagen.

Wat bind_hosts daadwerkelijk bestuurt

AdGuard Home'sdns.bind_hostsis de lijst van lokale adressen die de DNS-luisteraar gebruikt. De meegeleverde standaard is het wildcard-adres, wat betekent dat er op elk lokaal adres wordt geaccepteerd en dat de kernel het bronadres per antwoord kiest. Het vervangen van het wildcard-adres door het adres dat clients gebruiken om te vragen verandert de socket, en daarmee het bronadres bij elk antwoord.

De lijst kan meer dan één invoer bevatten, wat van belang is bij een resolver die twee netwerken bedient. Het vermelden van10.6.0.1en192.168.1.10geeft twee gebonden sockets, en een query die op een van beide binnenkomt wordt beantwoord vanuit het adres waarop het binnenkwam. Dat is het gedrag dat de meeste mensen veronderstellen dat het wildcard-already biedt.

De YAML is eenvoudig, en het adres hierin is het adres dat je tunnelclients moesten gebruiken, niet het primaire adres van de host:

dns:
  bind_hosts:
    - 10.6.0.1
  port: 53

Waarom twee installaties van één resolver het oneens zijn

Plugin-beheerd betekent in deze context dat de resolver is geïnstalleerd en wordt beheerd door een ander pakket: een router firmware pakket, een NAS-pakket of een home-automation add-on. Dat pakket levert meestal zijn eigen versie van AdGuard Home's YAML en start het proces opnieuw op op zijn eigen schema, terwijl een standalone instantie de binary of container van de leverancier is die je zelf configureert. In beide gevallen heb je te maken met twee onafhankelijke processen met aparte configuratiebestanden en aparte bindkeuzes, zelfs als beide dezelfde upstream-lijst en dezelfde filterlijsten lezen. De één kan het specifieke tunneladres binden terwijl de ander de wildcard overneemt, en de webinterface ziet er vanaf beide zijden identiek uit.

Dat is waarom "dezelfde resolver werkte vóór de migratie" niets bewijst over de huidige binding. Controleer de socket, en controleer vervolgens het configuratiebestand dat het lopende proces daadwerkelijk heeft geladen. Een verouderde kopie in een andere map is een veelvoorkomende reden dat de wijziging geen effect lijkt te hebben.

Pin het, en test vervolgens vanaf de tunnelzijde

Veranderbind_hostsnaar het tunneladres, herstart de service, en bevestig dat de socket is verplaatst:ss -lunp | grep :53zou nu10.6.0.1:53moeten tonen en geen wildcard-entry. Als het nog steeds0.0.0.0toont,leest het lopende proces het bestand dat je hebt bewerkt niet.

Test vervolgens vanaf de client, omdat dat de enige zijde is die ertoe doet. Een query metdig @10.6.0.1 example.comoefent het pad dat de gebruiker volgt, en een capture op de host mettcpdump -ni wg0 udp port 53Toont het bronadres van het antwoord op het netwerk. Vergelijk het met het adres in de resolverinstelling van de client; wanneer ze gelijk zijn, is de timeout geen mysterie meer.

ip route get 10.6.0.2Verklaart elke resterende eigenaardigheid, omdat het de interface en bron afdrukt die de host naar de client zou gebruiken. Als die output de LAN-interface noemt, is de wijziging van de bind niet de volledige oplossing en is de routeringstabel het volgende wat gelezen moet worden.

Wat de bind-instelling niet kan verhelpen

Het vastzetten van de listener repareert geen toegangslijst die het tunnel-subnet weglaat, een firewallregel die de query toestaat maar niet het antwoord, of een ontbrekende route terug naar het WireGuard-pool. Die falen eerder of later dan het bronadres, en elk heeft een andere eigenaar.

Het verandert ook nietnaar welke upstream de resolver doorstuurt, of rebindingbescherming een privéantwoord voor een privénnaam weigert, of hoe de client zijn eigen zoekdomeinen toepast. Dat zijn afzonderlijke controles. Wijzig het bind-adres wanneer de bron van het antwoord onjuist is, en verander iets anders wanneer dat niet het geval is.

Gerelateerde artikelen