Een LAN-apparaat presenteren op een van de eigen tunneladressen van de gateway kost één regel NAT. De verbinding mislukt alsnog, omdat het apparaat dat antwoordt geen idee heeft dat het adres van de client via die gateway bereikbaar is. Loop het pakket van de client naar binnen, loop daarna het antwoord terug naar buiten, en de ontbrekende helft wordt duidelijk.

Begin bij het perspectief van de client

De client in dit voorbeeld zit in de VPN-pool 10.62.0.0/24 en verbindt met 10.62.0.1 op poort 8080. Dat adres hoort bij de gateway zelf, dus het pakket komt aan in de kernel van de gateway en niet bij een andere peer. Achter de gateway is het LAN 172.21.4.0/24. De gateway heeft 172.21.4.10, en het apparaat dat echt HTTP bedient is 172.21.4.40.

Een adres dat bij een andere VPN-peer hoort is niet uitwisselbaar met het serviceadres van de gateway. Als de client verbindt met het adres van een peer, is er helemaal geen gateway-regel bij betrokken, en deze hele wandeling is de verkeerde.

Baken de doelmachinetranslatie bewust af

De smalle versie presenteert één poort en herschrijft alleen de bestemming. Het pakket behoudt zijn protocol en zijn bron, en dat maakt de rest van de wandeling interessant.

iptables -t nat -A PREROUTING -i tun0 -s 10.62.0.0/24 -d 10.62.0.1 -p tcp --dport 8080 -j DNAT --to-destination 172.21.4.40:80

Een regel zonder criteria voor protocol en poort is de brede versie: die behoudt welke poort de client ook koos en wijzigt alleen het adres. Dat is legitiem wanneer de hele host gepresenteerd moet worden, en onjuist wanneer één dienst de bedoeling was. Lees de regel terug en bevestig de interfacenaam. Een DNAT-regel op de verkeerde interface matcht niets, wat dezelfde time-out oplevert als een ontbrekende regel en een uur verspilt aan naar het apparaat kijken.

Laat de doorstuurgrens instemmen

Translatie wijzigt de header, ze verleent geen toestemming. Met een standaard drop-beleid heeft de doorgestuurde stroom zijn eigen acceptatie nodig, en de retourrichting heeft de regel voor gevestigde verbindingen nodig die je beleid waarschijnlijk al heeft.

iptables -A FORWARD -i tun0 -o lan0 -d 172.21.4.40 -p tcp --dport 80 -m conntrack --ctstate NEW -j ACCEPT
iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

Een onvoorwaardelijke acceptatie voor elke DNAT-stroom is breder dan dit ontwerp en staat ook mappingen toe die later iemand anders toevoegt. Benoem de bestemming en de poort, en laat de rest gesloten blijven. Als de tellers op de doorstuursregel op nul blijven terwijl de NAT-tellers stijgen, wordt het pakket vóór jouw regel weggegooid. Lees de ketenorde in plaats van een tweede kopie toe te voegen.

Het apparaat moet op de een of andere manier antwoorden

Na de translatie ziet het apparaat een bron in 10.62.0.0/24. Zijn antwoord gaat naar zijn standaardgateway, dat is de LAN-router, niet de VPN-gateway, tenzij iets hem anders vertelt. Twee regelingen lossen dat op, en ze zijn niet gelijkwaardig. Een route op het apparaat of op de LAN-router stuurt 10.62.0.0/24 naar 172.21.4.10 en behoudt de bron van de client. Een beperkte brontranslatie verbergt de client juist achter het LAN-adres van de gateway.

ip route add 10.62.0.0/24 via 172.21.4.10 dev eth1
iptables -t nat -A POSTROUTING -s 10.62.0.0/24 -d 172.21.4.40 -o lan0 -p tcp --dport 80 -j SNAT --to-source 172.21.4.10

Kies op basis van wat de dienst nodig heeft. Beleid per client en zinvolle logboeken willen de gerouteerde vorm; een apparaat waaraan geen route kan worden gegeven, of een dienst die simpelweg een LAN-adres moet zien, wijzen op de vertaalde vorm. Grijp niet naar een globale masquerade-regel om één antwoord te laten werken. Die verbergt elke client voor elke bestemming en breekt stil de beleidsregels die van bronadressen afhangen.

Test niet vanaf de gateway zelf

Een verzoek dat op de gateway naar 10.62.0.1 wordt gegenereerd, verlaat via de OUTPUT-keten, niet via de inkomende PREROUTING. Het falen of slagen zegt niets over de regel die naar de client kijkt, en zo concluderen mensen dat een werkende regel kapot is.

conntrack -L | grep 172.21.4.40
tcpdump -ni any 'port 8080 or port 80'

Voer een echt clientverzoek uit en lees beide. Het conntrack-item toont de toegepaste translatie, en de captures tonen of het verzoek naar het LAN is overgegaan en of er een antwoord terugkwam richting de tunnel. Gebruik een nieuwe verbinding na het wijzigen van regels, want bestaande status houdt zijn eerdere mapping en blijft op de oude manier falen. Bevestig daarna het hele gesprek: het adres van het apparaat, de doorstuurrecht en de antwoordroute beschrijven allemaal dezelfde stroom.

Gerelateerde artikelen