Twee ingenieurs met dezelfde OpenBSD-gateway geven je vaak twee verschillende regelsets om een extern netwerk te bereiken, en beide zijn verdedigbaar. De keuze tussen brontranslatie en een retourroute is helemaal geen syntaxiskwestie. Het komt neer op wat de andere kant al weet over 192.168.88.0/24 en wat je in je logs wilt bewaren. Doe je dat fout, dan ziet de nat-to-regel er perfect uit terwijl de antwoorden verdwijnen in de externe standaardgateway.

Routering en herschrijven beantwoorden verschillende vragen

De routetabel beslist dat 172.20.0.0/16 bereikbaar is via tun0, en die beslissing valt voordat er ook maar enige pf-translatie wordt geraadpleegd. Brontranslatie verandert vervolgens de pakketkop zodat de andere kant het tunneladres van de gateway ziet in plaats van een LAN-host. Geen van beide mechanismen vervangt het andere: een nat-regel kan geen route toveren, en een route kan een externe router die nog nooit van jouw privé-subnet heeft gehoord niet overtuigen. Als de andere kant geen retourpad heeft, worden antwoorden weggegooid of naar zijn standaardgateway gestuurd, en geen enkele regelaanpassing lost dat op.

Simpel gezegd beantwoordt doorsturen waar het verkeer heen gaat en beantwoordt translatie waar het vandaan lijkt te komen. Houd ze in aparte mentale vakjes terwijl je de regelset ontwerpt.

Drie voorwaarden die de doorslag geven

Stel drie vragen in volgorde en het ontwerp kiest zichzelf meestal. Heeft het externe netwerk een statische route die naar het tunneladres wijst voor 192.168.88.0/24, of beheert zijn beheerder de routers op dat pad? Als ja, laat de LAN-adressen ongewijzigd reizen en sla translatie helemaal over. Heb je zichtbaarheid per client aan de andere kant nodig, voor toegangsbeleid of voor een auditspoor? Als ja, dan is het behouden van de bron het routeringswerk waard. Is het tunneladres stabiel genoeg om in een externe route te schrijven, of verschuift het tussen herverbindingen?

Als een antwoord nee of onbekend is, is nat-to de pragmatische optie, en het is ook de omkeerbare. Een translatieregel gaat er in één regel uit zodra de andere kant een fatsoenlijke route toevoegt. Een retourroute die nooit is geïnstalleerd kost je een supportthread elke keer dat iemand vraagt waarom de tunnel maar één kant op werkt.

Het fragment zo plaatsen dat pf het echt evalueert

Het onderstaande fragment gaat ervan uit dat het LAN 192.168.88.0/24 is, het externe netwerk 172.20.0.0/16 en de tunnelinterface tun0. Niets erin kiest een volgende hop. Het herschrijft alleen de bron op pakketten die al door de tunnel naar buiten gaan.

match out on tun0 inet from 192.168.88.0/24 to 172.20.0.0/16 nat-to (tun0)
pass in on em0 inet from 192.168.88.0/24 to any keep state

Twee details in die eerste regel dragen het meeste gewicht. Haakjes rond tun0 vertellen pf om het interfaceadres te lezen telkens wanneer het een state-entry bouwt, wat uitmaakt wanneer de tunnel na een herverbinding opnieuw wordt genummerd. Het woord match betekent dat de regel herschrijft en dan doorvalt, dus een aparte pass-regel moet de stroom nog steeds toelaten. De interface die in de match-regel wordt genoemd moet ook degene zijn die de routetabel kiest, anders evalueert pf de regel op een ander uitgaand pad dan het pakket werkelijk neemt.

Vergeet de kernelkant niet. IPv4-doorsturen moet zijn ingeschakeld, en de stateful pass-regels voor tunnel en LAN moeten bestaan voordat dit alles betekenis heeft. De PF NAT-sectie van de OpenBSD FAQ is de juiste referentie voor de volgorde van de trefwoorden hier.

Verifieer de regelset voordat je het verkeer vertrouwt

Controleer eerst de syntaxis met pfctl -nf /etc/pf.conf, dat het bestand parseert zonder het te laden. Laad daarna het beleid en lees terug wat de kernel werkelijk vasthoudt, want een regel die schoon is geparseerd kan nog steeds overschaduwd zijn of aan de verkeerde interface hangen. pfctl -sn drukt translatieregels af in hun geladen vorm, en pfctl -sr drukt filterregels af in evaluatievolgorde.

Let daarna op de draad. Op de gateway laat tcpdump -ni tun0 'host 172.20.0.10' zien of het bronadres dat de tunnel verlaat het tunneladres of de LAN-host is. Een snelle netstat -rn -f inet bevestigt naar welke interface de bestemming resolvet. Zodra het verkeer stroomt, somt pfctl -ss state-entries op; als een stroom geen state opleverde, heeft het pakket nooit een regel geraakt die er een aanmaakt.

Als de tunnelkant er goed uitziet en de antwoorden nog steeds niet aankomen, stop dan met het bewerken van pf. De resterende fout zit op de externe router, waar het antwoord naar een privéadres wordt gestuurd dat die kant niet kan bereiken.

Wanneer translatie meer kost dan ze bespaart

Translatie verbergt clients, en soms is dat precies de verkeerde ruil. Overlappende subnetten zijn één geval: als de andere kant intern ook 192.168.88.0/24 gebruikt, maakt het presenteren van LAN-hosts als de gateway de botsing erger in plaats van beter. IPsec-beleid dat verkeer op adrespaar selecteert is een ander geval, omdat de beveiligingsbeleidsdatabase vóór de translatie wordt gematcht en je herschreven pakket nooit ziet. Elke uitrol die per gebruiker factureert, beperkt of auditeert verliest ook de identiteit die hij nodig heeft op het moment dat de bron tot één adres ineenklapt.

Draagbare pf-derivaten zijn een aparte valkuil. Producten die hun eigen regelbestanden genereren verwachten dat NAT via hun interface wordt geconfigureerd, en handmatig bewerkte fragmenten worden bij de volgende herlaad overschreven. Regelsets die zijn gekopieerd uit handleidingen van vóór het trefwoord match laden niet op een huidige kernel, dus port de syntaxis en lees de fout in plaats van te gissen.

De beslisregel die contact met echte netwerken overleeft is kort: installeer een retourroute wanneer je kunt, vertaal wanneer je niet kunt, en schrijf op welke van de drie voorwaarden je die keuze liet maken. Die notitie bespaart de volgende persoon een middag.

Gerelateerde artikelen