OpenVPN-DNS op de gateway: dnsmasq en de reikwijdte van de firewall
Draai dnsmasq op het tunneladres, sta DNS alleen toe vanuit de clientpool, push de resolver en test daarna directe query's en de eigen opzoeking van de app.
Clients op de tunnel bereiken de gateway, en de gateway bereikt de interne resolver, dus DNS zou moeten werken. Dat doet het niet, want dat zijn twee verschillende rechten en een werkende DNS-dienst is een derde ding. De listener moet bestaan op een adres dat de clients bereiken, de firewall moet query's naar dat adres toestaan, en de client moet te horen krijgen dat hij hem gebruikt. De tunnel in beide richtingen openzetten lost de eerste twee bij toeval op en laat de derde ongedaan.
De listener is een lokale dienst met twee richtingen
Inkomend stuurt een client een query naar het tunneladres van de gateway op poort 53. Uitgaand stuurt de daemon die query door naar zijn geconfigureerde upstream. Beide helften moeten werken, en ze falen op verschillende manieren.
Een time-out die de client meldt en een time-out die op de gateway te zien is, zijn niet dezelfde storing.
Bind het tunneladres, niet elk adres
Een aparte dnsmasq-instantie voor deze taak heeft een expliciet luisteradres nodig, een bindmodus die het verschijnen van de tunnel na de start verdraagt, en één duidelijke upstream. Dit is de kleinste versie die ik gebruik:
listen-address=127.0.0.1,10.90.0.1
bind-dynamic
no-resolv
no-hosts
server=192.168.50.53
bind-dynamic bindt de afzonderlijke adressen en gaat om met het geval dat tun0 later verschijnt, wat uitmaakt op een host waar de VPN-dienst herstart. loopback vermelden houdt lokale hulpmiddelen werkend zonder een openbare listener toe te voegen. no-resolv voorkomt dat de daemon upstreams erft uit de resolverconfiguratie van de host, en no-hosts voorkomt dat deze instantie het hosts-bestand van de gateway publiceert. Geen van die opties geeft iemand toestemming om de dienst te bevragen.
Controleer of er al een listener op poort 53 is voordat je een tweede daemon start, en gebruik de configuratie-eigenaar van de distributie in plaats van een verdwaald bestand in de verkeerde map.
Sta DNS-invoer toe, geen tunnelverkeer
De firewallregels die dit laten werken zijn lokale invoerregels, beperkt tot de tunnelinterface, de clientpool, het gatewayadres en poort 53. Twee regels, één per protocol, zijn genoeg:
sudo ufw allow in on tun0 proto udp from 10.90.0.0/24 to 10.90.0.1 port 53
sudo ufw allow in on tun0 proto tcp from 10.90.0.0/24 to 10.90.0.1 port 53
DNS draait over TCP net als over UDP, dus een regel alleen voor UDP laat grote antwoorden mislukken op een manier die onregelmatig lijkt. Dit zijn geen ufw route rechten, en ze mogen geen brede toestemming op tun0 worden. De volgorde is net zo belangrijk als de inhoud: een eerdere regel die alle invoer van tun0 weggooit, wint nog steeds, en een toestemming onder een terminale drop toevoegen levert niets op.
Als gateway-DNS nu deel van het ontwerp is, herzie dat eerdere beleid dan bewust en leg vast waarom.
De upstreamhelft is een apart pad
Query's verlaten de gateway vanaf zijn eigen adres richting de upstream-resolver, dus de route van de gateway en het uitgaande beleid naar die resolver moeten de uitwisseling toestaan. Dat is een andere regel dan die clients bij de listener laat, en hij faalt met een ander symptoom.
Voeg geen onbeperkte tunneluitvoer toe om antwoorden te laten werken; gevolgde antwoorden hebben dat niet nodig.
Push de optie en controleer daarna de overdracht
De server kan de resolver aan clients aankondigen met een gepushte optie. Dat is een optie, geen instructie die het besturingssysteem moet opvolgen:
push "dhcp-option DNS 10.90.0.1"
Een Linux-opdrachtregelclient heeft misschien de resolverintegratie van zijn verbindingsbeheerder nodig, en een beheerd apparaat heeft misschien een bijgewerkt beheerprofiel nodig. Bevestig de actieve resolver op de client na het verbinden in plaats van aan te nemen dat de push is toegepast. Wanneer twee mechanismen tegelijk DNS proberen te zetten, krijg je een race die zich voordoet als flikkerende resolutie.
Het doel is één eigenaar voor de resolverconfiguratie van de client, en de push is die eigenaar meestal alleen als het clientplatform het eens is.
Test wat je echt hebt gebouwd
Bevraag één private volledig gekwalificeerde naam en één toegestane externe naam rechtstreeks tegen het tunneladres, over zowel UDP als TCP. Herhaal daarna via het gewone zoekpad van de applicatie.
Als de directe query's werken en de applicatie nog steeds faalt, zit de fout in de overdracht en niet op de server:
- De client heeft de gepushte optie nooit toegepast.
- Een andere resolver werd later ingesteld en won de race.
- De applicatie gebruikt zijn eigen resolverbibliotheek of een gecacht antwoord.
Sluit af met de bevestiging dat een bron buiten het goedgekeurde VPN-pad de listener helemaal niet kan gebruiken. Een geslaagde resolutie machtigt het adres dat hij teruggaf niet, dus houd die twee vragen gescheiden.