Je verwacht een tunnelinterface, je zoekt ernaar, en er is niets in de firewall om aan te koppelen. Dat is normaal voor een op beleid gebaseerde gateway: de versleutelde uitwisseling komt binnen op de fysieke interface, en het ontsleutelde interne pakket dat daarna wordt doorgestuurd, wordt ook waargenomen als aankomend op diezelfde interface. Er is geen tun0 omdat niets er een heeft gemaakt.

Het interne verzoek is nog steeds een apart pakket met zijn eigen bron, bestemming en dienst, en de kernel weet uit welke beveiligingsassociatie het kwam. Die kennis kan een firewallregel koppelen.

Twee pakketten, één interface

Stel je de inkomende richting voor. Een met ESP of UDP ingekapseld pakket komt binnen, de kernel vindt het bijbehorende beleid, ontsleutelt het en geeft het heldere pakket door aan het doorstuurpad. Een regel die alleen naar de interfacenaam kijkt, kan dat pakket niet onderscheiden van ander verkeer dat op dezelfde draad aankomt.

Wat het onderscheidt, is de context van het inkomende beveiligingspad die aan het pakket hangt. nftables toont die als meta ipsec exists, wat waar is wanneer het pakket via een IPsec-beveiligingspad is aangekomen. Combineer die met de clientpool, de bestemming en de dienst, en de regel wordt specifiek genoeg om veilig te zijn.

De context weglaten is de gebruikelijke fout, en het is een beveiligingsfout en geen cosmetische. Een regel die alles accepteert wat uit de clientpool komt, accepteert net zo graag een vervalst pakket uit het lokale netwerk, want het bronadres is op zichzelf geen bewijs van iets. De context van het beveiligingspad is de goedkoopste manier om de bron betekenisvol te maken. Schrijf de regel er vanaf het begin mee, in plaats van die na een audit toe te voegen.

Schrijf de doorstuurregel

Stel een geauthenticeerde IPv4-toegang op afstand voor met clients in 10.90.0.0/24 en één goedgekeurde bestemming op 203.0.113.40. Een regelfragment voor die stroom ziet er zo uit.

meta ipsec exists ip saddr 10.90.0.0/24 \
  ip daddr 203.0.113.40 tcp dport 443 \
  oifname "eth0" counter accept

De adressen en de interface zijn voorbeelden om te vervangen. Plaats het beoordeelde equivalent in het doorstuurbeled vóór de regel die de stroom anders zou weigeren, en leeg geen bestaande regelset om het te installeren; een gateway is geen cleanroom-experiment.

De term oifname is het waard om te behouden. Hij documenteert de uitgaande beslissing en voorkomt dat de regel overeenkomt in een richting die je niet bedoelde, wat uitmaakt op een gateway met meerdere paden naar het internet. Op een testdoos met één uplink lijkt de term overbodig, en precies daarom wordt hij verwijderd voordat de doos een tweede uplink krijgt.

Machtigingen voor de buitenste uitwisseling staan apart. Het ingangspad van de gateway heeft de IKE- en ESP- of UDP-inkapselingspoorten nodig die hij werkelijk gebruikt, en die machtigingen staan niets toe met betrekking tot het ontsleutelde pakket binnenin. De twee door elkaar halen is de manier waarop een werkende tunnel eindigt met een firewall die alles doorstuurt.

Inkomende context is geen uitgaande context

Dezelfde familie uitdrukkingen dekt de andere richting met rt ipsec, dat de uitgaande beveiligingsassociatie beschrijft die een pakket zal gebruiken. Het beantwoordt een andere vraag: niet waar dit pakket vandaan kwam, maar of het op zijn volgende traject beschermd zal zijn.

Dat onderscheid is belangrijk op een gateway die tegelijk één tunnel beëindigt en naar een andere doorstuurt. Een pakket kan ontsleuteld aankomen en toch versleuteld moeten vertrekken, en een acceptatie die alleen voor de inkomende context is geschreven, zegt niets over de uitgaande eis. Als het beleid die bescherming vereist, zou de regelset die moeten uitdrukken in plaats van aan te nemen dat de routering het regelt.

Houd de twee vragen in aparte regels zodat de lezer ziet welke wordt afgedwongen. Eén slimme regel die beide controleert, is moeilijker te beoordelen en veel moeilijker te debuggen wanneer de ene helft niet meer overeenkomt. Twee regels met tellers vertellen je ook welke eis faalt, wat één gecombineerde regel nooit zal doen.

NAT is geen firewallbeslissing

Verkeer naar het internet vanuit een private clientpool heeft meestal bronvertaling nodig zodat het antwoord de weg terug vindt. Maar verkeer dat voor een ander uitgaand IPsec-beleid is geselecteerd, moet zijn vereiste uitzondering behouden, en elke private bron maskeren zonder aan de volgende beschermingsbeslissing te denken breekt dat.

Een acceptatie binnen een NAT-keten is ook geen algemene toestemming. NAT en filtering hebben verschillende taken, en een NAT-keten onderzoekt niet elk later pakket van een gevestigde stroom, en daarom levert erop vertrouwen voor beveiliging regels op die in tests lijken te werken en onder belasting falen.

Het omgekeerde is ook waar en verrast mensen: een acceptatie ergens in de ene filterbasis-keten weegt niets tegen een latere drop in een andere toepasselijke keten. Volgorde en bereik van de keten bepalen de uitkomst, niet de aanwezigheid van een acceptatie in het bestand.

Controleer de exacte interne dienst

Test de specifieke bestemming en poort die je hebt toegestaan, vanaf een echte client, en bevestig dat het antwoord terugkomt. Test daarna iets dat je niet hebt toegestaan en controleer dat het er niet doorheen gaat, want een te brede regel slaagt voor de eerste test net zo goed als een juiste. Een verzoek dat de client nooit verlaat, is ook geen firewallresultaat, dus lees de tellers om te zien of het pakket überhaupt is geëvalueerd. Twee tests en één telleraflezing vertellen je meer dan een hele middag regelset lezen.

De nftables-referentie documenteert meta ipsec, rt ipsec en de richtingspecifieke uitdrukkingen, en daar controleer je de syntaxis tegen je geïnstalleerde versie. En houd de reikwijdte expliciet: dit is een IPv4-voorbeeld, het zegt niets over IPv6, en het maakt willekeurige openbare poortdoorschakeling geen deel van de VPN-dienst.

Gerelateerde artikelen