Du förväntar dig ett tunnelgränssnitt, letar efter det, och det finns inget att matcha i brandväggen. Det är normalt för en policybaserad gateway: det krypterade utbytet anländer på det fysiska gränssnittet, och det dekrypterade inre paketet som sedan vidarebefordras observeras också anlända på samma gränssnitt. Det finns ingen tun0 eftersom inget skapade en.

Den inre förfrågan är fortfarande ett eget paket med sin egen källa, destination och tjänst, och kärnan vet vilken säkerhetsassociation den kom ut ur. Det är den kunskapen en brandväggsregel kan matcha.

Två paket, ett gränssnitt

Föreställ dig den inkommande riktningen. Ett ESP- eller UDP-inkapslat paket anländer, kärnan hittar den matchande policyn, dekrypterar det och lämnar det klara paketet till vidarebefordringsvägen. En regel som bara tittar på gränssnittsnamnet kan inte skilja det paketet från annan trafik som anländer på samma kabel.

Det som skiljer det är kontexten för den inkommande säkerhetsvägen som är kopplad till paketet. nftables exponerar den som meta ipsec exists, vilket är sant när paketet anlände via en IPsec-säkerhetsväg. Kombinera den med klientpoolen, destinationen och tjänsten, och regeln blir specifik nog att vara säker.

Att utelämna kontexten är det vanliga misstaget, och det är ett säkerhetsmisstag snarare än ett kosmetiskt. En regel som accepterar allt som kommer från klientpoolen accepterar lika gärna ett förfalskat paket från det lokala nätet, eftersom källadressen i sig inte är bevis för något. Kontexten för säkerhetsvägen är det billigaste sättet att göra källan meningsfull. Skriv regeln med den från början i stället för att lägga till den efter en granskning.

Skriv vidarebefordringsregeln

Anta en autentiserad IPv4-fjärråtkomsttjänst med klienter i 10.90.0.0/24 och en godkänd destination på 203.0.113.40. Ett regelfragment för det flödet ser ut så här.

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

Adresserna och gränssnittet är exempel att ersätta. Placera den granskade motsvarigheten i vidarebefordringspolicyn före regeln som annars skulle avvisa flödet, och töm inte en befintlig regeluppsättning för att installera den; en gateway är inte ett rent-rum-experiment.

Uttrycket oifname är värt att behålla. Det dokumenterar utgångsbeslutet och hindrar regeln från att matcha i en riktning du inte avsåg, vilket spelar roll på en gateway med flera vägar till internet. På en testlåda med en enda upplänk verkar uttrycket överflödigt, och det är just därför det tas bort innan lådan får en andra upplänk.

Behörigheterna för det yttre utbytet är separata. Gatewayens ingångsväg behöver de IKE- och ESP- eller UDP-inkapslingsportar som den faktiskt använder, och dessa behörigheter tillåter ingenting om det dekrypterade paketet inuti. Att blanda de två är sättet en fungerande tunnel hamnar med en brandvägg som vidarebefordrar allt.

Inkommande kontext är inte utgående kontext

Samma familj av uttryck täcker den andra riktningen med rt ipsec, som beskriver den utgående säkerhetsassociation som ett paket kommer att använda. Det svarar på en annan fråga: inte varifrån detta paket kom, utan om det kommer att skyddas på sin nästa sträcka.

Den skillnaden spelar roll på en gateway som avslutar en tunnel och samtidigt vidarebefordrar in i en annan. Ett paket kan anlända dekrypterat och ändå behöva lämna krypterat, och ett accepterande som bara skrivits för den inkommande kontexten säger ingenting om kravet på utgående. Om policyn kräver det skyddet bör regeluppsättningen uttrycka det i stället för att anta att routningen ordnar det.

Håll de två frågorna i separata regler så att läsaren ser vilken som tillämpas. En enda smart regel som kontrollerar båda är svårare att granska och mycket svårare att felsöka när den ena halvan slutar matcha. Två regler med räknare berättar också vilket krav som misslyckas, vilket en kombinerad regel aldrig gör.

NAT är inte ett brandväggsbeslut

Trafik mot internet från en privat klientpool behöver vanligtvis källöversättning så att svaret hittar vägen tillbaka. Men trafik som valts för en annan utgående IPsec-policy måste behålla sitt nödvändiga undantag, och att maskera varje privat källa utan att tänka på nästa skyddsbeslut bryter det.

Ett accepterande inne i en NAT-kedja är inte heller ett allmänt tillstånd. NAT och filtrering har olika uppgifter, och en NAT-kedja granskar inte varje senare paket i ett etablerat flöde, och det är just därför att förlita sig på den för säkerhet ger regler som verkar fungera i test och misslyckas under belastning.

Det omvända är också sant och överraskar folk: ett accepterande någonstans i en filterbaskedja väger ingenting mot en senare avvisning i en annan tillämplig kedja. Ordningen och kedjans omfattning avgör resultatet, inte förekomsten av ett accepterande i filen.

Verifiera den exakta inre tjänsten

Testa den specifika destination och port som du godkände, från en riktig klient, och bekräfta att svaret kommer tillbaka. Testa sedan något du inte godkände och kontrollera att det inte går igenom, eftersom en för bred regel klarar det första testet lika bra som en korrekt. En förfrågan som aldrig lämnar klienten är inte heller ett brandväggsresultat, så läs räknarna för att se om paketet alls utvärderades. Två tester och en räknaravläsning berättar mer för dig än en hel eftermiddag med att läsa regeluppsättningen.

nftables-referensen dokumenterar meta ipsec, rt ipsec och de riktningsspecifika uttrycken, och det är där man kontrollerar syntaxen mot sin installerade version. Och håll omfattningen explicit: det här är ett IPv4-exempel, det säger ingenting om IPv6, och det gör inte godtycklig vidarebefordran av offentliga portar till en del av VPN-tjänsten.

Relaterade artiklar