Introduktion till Kubernetes nätverkspolicyer för säkerhetsspecialister

Introduktion till Kubernetes nätverkspolicyer för säkerhetsspecialister

Obs. övers.: Artikelförfattaren — Reuven Harrison — har över 20 års erfarenhet av mjukvaruutveckling och är för närvarande teknisk direktör och medgrundare av företaget Tufin, som skapar lösningar för hantering av säkerhetspolicyer. Medan han betraktar Kubernetes-nätverkspolicyer som ett kraftfullt verktyg för nätverkssegmentering i kluster, anser han att de inte är så lätta att tillämpa i praktiken. Denna material (ganska omfattande) syftar till att öka medvetenheten hos specialister inom detta område och hjälpa dem att skapa nödvändiga konfigurationer.

Idag väljer allt fler företag Kubernetes för att köra sina applikationer. Intresset för denna programvara är så stort att vissa kallar Kubernetes för 'det nya operativsystemet för datacenter'. Gradvis börjar Kubernetes (eller k8s) uppfattas som en kritisk del av verksamheten, som kräver organisation av mogna affärsprocesser, inklusive nätverkssäkerhet.

För säkerhetsspecialister som har problem med att arbeta med Kubernetes kan plattformens standardpolicy visa sig vara en riktig ögonöppnare: att tillåta allt.

Den här guiden hjälper dig att förstå den interna strukturen av nätverkspolicyer; att se skillnaderna mellan dem och reglerna för vanliga brandväggar. Det kommer också att diskuteras några fallgropar och ges rekommendationer som hjälper till att skydda applikationer i Kubernetes.

Kubernetes-nätverkspolicyer

Kubernetes nätverkspolicymekanism gör det möjligt att hantera interaktionen mellan applikationer som körs på plattformen på nätverksnivå (det tredje lagret i OSI-modellen). Nätverkspolicyer saknar vissa avancerade funktioner som moderna brandväggar erbjuder, såsom 7:e lagret OSI-kontroll och hotidentifiering, men de ger en grundläggande nivå av nätverkssäkerhet som är en bra utgångspunkt.

Nätverkspolicyer kontrollerar kommunikationen mellan poddar

Arbetsbelastningar i Kubernetes fördelas över poddar, som består av en eller flera containrar som körs tillsammans. Kubernetes tilldelar varje pod en IP-adress som är tillgänglig från andra poddar. Nätverkspolicys i Kubernetes ställer in åtkomsträttigheter för grupper av poddar på samma sätt som säkerhetsgrupper i molnet används för att hantera åtkomst till virtuella maskininstanser.

Definition av nätverkspolicys

Precis som andra resurser i Kubernetes definieras nätverkspolicys med YAML-språket. I exemplet nedan får applikationen balance åtkomst till postgres:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.postgres
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: postgres
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: balance
  policyTypes:
  - Ingress

Introduktion till Kubernetes nätverkspolicyer för säkerhetsspecialister

(Obs. övers.: den här skärmbilden, liksom alla efterföljande liknande, skapades inte av inbyggda medel i Kubernetes, utan med hjälp av verktyget Tufin Orca, vars utveckling står bakom företaget till den ursprungliga artikeln och som nämns i slutet av materialet.)

För att definiera din egen nätverkspolicy behövs grundläggande kunskaper i YAML. Detta språk baseras på indrag (definierat med mellanslag, inte tabb). Ett element med indrag tillhör det närmaste elementet med indrag ovanför det. Ett nytt listelement börjar med ett bindestreck, alla andra element har formen nyckel-värde.

När du har beskrivit policyn i YAML, använd kubectl, för att skapa den i klustret:

kubectl create -f policy.yaml

Specifikation av nätverkspolicy

Specifikationen av Kubernetes nätverkspolicy omfattar fyra element:

  1. podSelector: definierar de poddar som påverkas av denna policy (mål) — obligatoriskt;
  2. policyTypes: anger vilka typer av policys som ingår i denna: ingress och/eller egress — valfritt, men jag rekommenderar att det anges tydligt i alla fall;
  3. ingress: definierar den tillåtna inkommande trafiken till målpoddarna — valfritt;
  4. egress: definierar den tillåtna utgående trafik från målpoddarna — valfritt.

Exemplet, lånat från Kubernetes-webbplatsen (jag har ersatt role till app), visar hur alla fyra element används:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default
spec:
  podSelector:    # <<<
    matchLabels:
      app: db
  policyTypes:    # <<<
  - Ingress
  - Egress
  ingress:        # <<<
  - from:
    - ipBlock:
        cidr: 172.17.0.0/16
        except:
        - 172.17.1.0/24
    - namespaceSelector:
        matchLabels:
          project: myproject
    - podSelector:
        matchLabels:
          role: frontend
    ports:
    - protocol: TCP
      port: 6379
  egress:         # <<<
  - to:
    - ipBlock:
        cidr: 10.0.0.0/24
    ports:
    - protocol: TCP
      port: 5978

Introduktion till Kubernetes nätverkspolicyer för säkerhetsspecialister
Introduktion till Kubernetes nätverkspolicyer för säkerhetsspecialister

Observera att det inte är nödvändigt att inkludera alla fyra element. Endast podSelectorär obligatoriska, de övriga parametrarna kan användas på önskemål.

Om du hoppar över policyTypeskommer policyn att tolkas enligt följande:

  • Som standard antas den definiera ingress-sidan. Om det inte finns några direkta angivelser om detta i policyn, kommer systemet att anse att all trafik är förbjuden.
  • Beteendet på egress-sidan kommer att bestämmas av förekomsten eller frånvaron av motsvarande egress-parameter.

För att undvika fel, rekommenderar jag att alltid ange tydligt policyTypes.

I enlighet med ovanstående logik, om parametrarna ingress och/eller egress utelämnas, kommer policyn att förbjuda all trafik (se "Röjningsregeln" nedan).

Standardpolicyn är att tillåta

Om inga policyer definieras, tillåter Kubernetes som standard all trafik. Alla poddar kan fritt utbyta information med varandra. Ur säkerhetssynpunkt kan detta verka ologiskt, men kom ihåg att Kubernetes skapades av utvecklare för att säkerställa interaktion mellan applikationer. Nätverkspolicyn lades till senare.

Namnområden

Namnområden (Namespaces) är en mekanism för samarbete i Kubernetes. De är avsedda att isolera logiska miljöer från varandra, samtidigt som datautbyte mellan namnområden som standard är tillåtet.

Precis som de flesta komponenter i Kubernetes finns nätverkspolicyer inom ett specifikt namnområde. I blocket metadata kan du ange vilket namnområde policyn tillhör:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: my-namespace  # <<<
spec:
...

Om namnområdet i metadata inte anges tydligt, kommer systemet att använda namnområdet som anges i kubectl (som standard namespace=default):

kubectl apply -n my-namespace -f namespace.yaml

Jag rekommenderar att tydligt ange namnområde, om du inte skriver en politik avsedd för flera namnrymder samtidigt.

Huvud element podSelector i policyn kommer att välja poddar från den namnrymd som policyn tillhör (den har inte åtkomst till poddar från andra namnrymder).

På samma sätt kan podSelectorar i ingress- och egressblock välja poddar endast från sin egen namnrymd, såvida du inte sammanfogar dem med namespaceSelector (detta kommer att diskuteras i avsnittet "Filtrera efter namnrymder och poddar").

Namngivningsregler för policys

Policyer har unika namn inom en namnrymd. Det kan inte finnas två policys med samma namn inom en namnrymd, men det kan finnas policys med samma namn i olika namnrymder. Det är praktiskt när du vill återanvända samma policy i flera namnrymder.

Jag gillar särskilt ett av namngivningssätten. Det innebär att kombinera namnrymden med mål-poddarna. Till exempel:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.postgres  # <<<
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: postgres
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: admin
  policyTypes:
  - Ingress

Introduktion till Kubernetes nätverkspolicyer för säkerhetsspecialister

Etiketter

Anpassade etiketter kan kopplas till Kubernetes-objekt som poddar och namnrymder. Etiketter (labels — är motsvarigheten till taggar i molnet. Kubernetes nätverkspolicys använder etiketter för att välja podar, som de tillämpas på:

podSelector:
  matchLabels:
    role: db

… eller namnrymder, som de tillämpas på. I detta exempel väljs alla poddar i namnrymder med motsvarande etiketter:

namespaceSelector:
  matchLabels:
    project: myproject

Ett varning: när du använder namespaceSelector se till att de valda namnrymderna innehåller den nödvändiga etiketten. Tänk på att inbyggda namnrymder, som default och kube-system, som standard inte innehåller några etiketter.

Du kan lägga till en etikett till en namnrymd på följande sätt:

kubectl label namespace default namespace=default

Där ska namespace i avsnittet metadata referera till det faktiska namnet på namnrymden, inte etiketten:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default   # <<<
spec:
...

Källa och mottagare

Brandväggspolicyer består av regler med källor och destinationer. Nätverkspolicyer i Kubernetes definieras för ett mål — en uppsättning poddar som de tillämpas på, och ställer sedan in regler för inkommande (ingress) och/eller utgående (egress) trafik. I vårt exempel kommer målet för policyn att vara alla poddar i namnutrymmet default med en etikett med nyckeln app och värdet db:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: db   # <<<<
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - ipBlock:
        cidr: 172.17.0.0/16
        except:
        - 172.17.1.0/24
    - namespaceSelector:
        matchLabels:
          project: myproject
    - podSelector:
        matchLabels:
          role: frontend
    ports:
    - protocol: TCP
      port: 6379
  egress:
  - to:
    - ipBlock:
        cidr: 10.0.0.0/24
    ports:
    - protocol: TCP
      port: 5978

Introduktion till Kubernetes nätverkspolicyer för säkerhetsspecialister
Introduktion till Kubernetes nätverkspolicyer för säkerhetsspecialister

Underavdelning ingress i denna policy öppnar inkommande trafik till målpoddarna. Med andra ord är ingress källan, och målet är den korresponderande destinationen. På samma sätt är egress destinationen, och målet är dess källa.

Introduktion till Kubernetes nätverkspolicyer för säkerhetsspecialister

Det är ekvivalent med två regler för brandväggen: Ingress → Mål; Mål → Egress.

Egress och DNS (viktigt!)

Genom att begränsa utgående trafik, var särskilt uppmärksam på DNS — Kubernetes använder denna tjänst för att mappa tjänster till IP-adresser. Till exempel kommer följande policy inte att fungera eftersom du inte har tillåtit applikationen balance att få åtkomst till DNS:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.balance
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: balance
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: postgres
  policyTypes:
  - Egress

Introduktion till Kubernetes nätverkspolicyer för säkerhetsspecialister

Det kan åtgärdas genom att öppna tillgången till DNS-tjänsten:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.balance
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: balance
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: postgres
  - to:               # <<<<
    ports:            # <<<<
    - protocol: UDP   # <<<<
      port: 53        # <<<<
  policyTypes:
  - Egress

Introduktion till Kubernetes nätverkspolicyer för säkerhetsspecialister

Den sista punkten till — är tom och därmed väljer den indirekt alla poddar i alla namnutrymmen, vilket tillåter balance att skicka DNS-förfrågningar till den korresponderande Kubernetes-tjänsten (den körs vanligtvis i namnutrymnet kube-system).

Denna metod fungerar, men den är överdrivet tillåtande och osäker, eftersom den tillåter att DNS-förfrågningar dirigeras utanför klustret.

Den kan förbättras med tre steg.

1. Tillåt endast DNS-förfrågningar inuti till klustret genom att lägga till namespaceSelector:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.balance
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: balance
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: postgres
  - to:
    - namespaceSelector: {} 
    ports:
    - protocol: UDP
      port: 53
  policyTypes:
  - Egress

Introduktion till Kubernetes nätverkspolicyer för säkerhetsspecialister

2. Tillåt DNS-förfrågningar endast inom namnområdet kube-system.

För detta behöver du lägga till en etikett i namnområdet kube-system: kubectl label namespace kube-system namespace=kube-system — och ange den i policyn med hjälp av namespaceSelector:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.balance
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: balance
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: postgres
  - to:
    - namespaceSelector:         
        matchLabels:             
          namespace: kube-system 
    ports:
    - protocol: UDP
      port: 53
  policyTypes:
  - Egress

Introduktion till Kubernetes nätverkspolicyer för säkerhetsspecialister

3. Paranoikern kan gå längre och begränsa DNS-förfrågningar till en specifik DNS-tjänst i kube-system. I avsnittet "Filtrera efter namnområden och poddar" kommer det att förklaras hur man uppnår detta.

Ett annat alternativ är att tillåta DNS på namnområdesnivå. I så fall behöver det inte öppnas för varje tjänst:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.dns
  namespace: default
spec:
  podSelector: {} 
  egress:
  - to:
    - namespaceSelector: {}
    ports:
    - protocol: UDP
      port: 53
  policyTypes:
  - Egress

Tom podSelector väljer alla poddar i namnområdet.

Introduktion till Kubernetes nätverkspolicyer för säkerhetsspecialister

Första överensstämmelsen och ordningen för regler

I vanliga brandväggar bestäms åtgärden ("Tillåt" eller "Förbjud") för ett paket av den första regeln som det uppfyller. I Kubernetes har policyn ingen betydelse.

Som standard, när inga regler är angivna, tillåts kommunikation mellan poddar och de kan fritt utbyta information. Så snart du börjar formulera policyer, blir varje pod som påverkas av minst en av dem isolerad enligt disjunktion (logiskt ELLER) av alla policyer som valt det. Poddar som inte påverkas av någon policy förblir öppna.

Detta beteende kan ändras med hjälp av en städsregel.

Städsregeln ("Förbjud")

Brandväggspolicyn blockerar vanligtvis all trafik som inte uttryckligen tillåtits.

I Kubernetes finns det ingen åtgärd "förbjuda" (deny), men en liknande effekt kan uppnås med en vanlig (tillåtande) policy genom att välja en tom grupp av poddar för indata (ingress):

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Ingress

Introduktion till Kubernetes nätverkspolicyer för säkerhetsspecialister

Denna policy väljer alla pods i namnområdet och lämnar ingress obestämd, vilket förhindrar hela inkommande trafik.

På liknande sätt kan hela utgående trafik från namnområdet begränsas:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all-egress
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Egress

Introduktion till Kubernetes nätverkspolicyer för säkerhetsspecialister

Observera att alla ytterligare policyer som tillåter trafik till pods i namnområdet kommer att ha företräde framför denna regel (på samma sätt som att lägga till en tillåtande regel före en förhindrande i brandväggens konfiguration).

Tillåt allt (Any-Any-Any-Allow)

För att skapa en "Tillåt allt" policy, behöver du komplettera den ovanstående förhindrande policyn med en tom post ingress:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-all
  namespace: default
spec:
  podSelector: {}
  ingress: # <<<
  - {}     # <<<
  policyTypes:
  - Ingress

Introduktion till Kubernetes nätverkspolicyer för säkerhetsspecialister

Den öppnar åtkomst från alla pods i alla namnområden (och alla IP-adresser) till vilken pod som helst i namnområdet default. Detta beteende är aktiverat som standard, så det behöver vanligtvis inte definieras ytterligare. Men ibland kan det vara nödvändigt att tillfälligt inaktivera vissa specifika tillstånd för att diagnostisera ett problem.

Regeln kan snävas och tillåta åtkomst endast till ett specifikt set av pods (app:balance) i namnområdet default:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-all-to-balance
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: balance
  ingress: 
  - {}
  policyTypes:
  - Ingress

Introduktion till Kubernetes nätverkspolicyer för säkerhetsspecialister

Den följande policyn tillåter all inkommande (ingress) och utgående (egress) trafik, inklusive åtkomst till vilken IP som helst utanför klustret:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-all
spec:
  podSelector: {}
  ingress:
  - {}
  egress:
  - {}
  policyTypes:
  - Ingress
  - Egress

Introduktion till Kubernetes nätverkspolicyer för säkerhetsspecialister
Introduktion till Kubernetes nätverkspolicyer för säkerhetsspecialister

Kombinera flera policys

Policer kombineras med logiskt ELLER på tre nivåer; tillstånden för varje pod fastställs enligt disjunktionen av alla policies som påverkar den:

1. I fälten från och till kan tre typer av element definieras (alla kombineras med ELLER):

  • namespaceSelector — väljer hela namnområdet;
  • podSelector — väljer pods;
  • ipBlock — väljer en subnät.

Antalet element (även om de är desamma) i underavsnitt från/till är inte begränsat. Alla kommer att kombineras med logiskt ELLER.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.postgres
  namespace: default
spec:
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: indexer
    - podSelector:
        matchLabels:
          app: admin
  podSelector:
    matchLabels:
      app: postgres
  policyTypes:
  - Ingress

Introduktion till Kubernetes nätverkspolicyer för säkerhetsspecialister

2. Inom policyn kan avsnittet ingress ha flera element från (de kombineras med logiskt ELLER). På samma sätt kan avsnittet egress inkludera flera element till (som också kombineras med disjunktion):

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.postgres
  namespace: default
spec:
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: indexer
  - from:
    - podSelector:
        matchLabels:
          app: admin
  podSelector:
    matchLabels:
      app: postgres
  policyTypes:
  - Ingress

Introduktion till Kubernetes nätverkspolicyer för säkerhetsspecialister

3. Olika policys kombineras också med logiskt ELLER

Men det finns en begränsning på vilket att Chris Cooney: Kubernetes kan endast kombinera policys med olika policyTypes (Ingress eller Egress). Policys som definierar ingress (eller egress) kommer att överskriva varandra.

Kommunikation mellan namnområden

Som standard är informationsutbyte mellan namnområden tillåtet. Detta kan ändras med en restriktiv policy som begränsar utgående och/eller inkommande trafik till namnområdet (se "Rensningsregel" ovan).

Genom att blockera åtkomst till namnområdet (se "Rensningsregel" ovan) kan du göra undantag från den restriktiva policyn genom att tillåta anslutningar från ett visst namnområde med hjälp av namespaceSelector:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: database.postgres
  namespace: database
spec:
  podSelector:
    matchLabels:
      app: postgres
  ingress:
  - from:
    - namespaceSelector: # <<<
        matchLabels:
          namespace: default
  policyTypes:
  - Ingress

Introduktion till Kubernetes nätverkspolicyer för säkerhetsspecialister

Som ett resultat kommer alla poddar i namnområdet default att få åtkomst till poddar postgres i namnrymden database. Men vad händer om du vill öppna åtkomst till postgres endast vissa specifika poddar i namnområdet default?

Filter för namnområden och poddar

Kubernetes version 1.11 och senare tillåter kombination av operatorer namespaceSelector och podSelector med hjälp av logiskt OCH. Detta ser ut på följande sätt:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: database.postgres
  namespace: database
spec:
  podSelector:
    matchLabels:
      app: postgres
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          namespace: default
      podSelector: # <<<
        matchLabels:
          app: admin
  policyTypes:
  - Ingress

Introduktion till Kubernetes nätverkspolicyer för säkerhetsspecialister

Varför uppfattas detta som OCH istället för det vanliga ELLER?

Observera att podSelector börjar inte med ett bindestreck. I YAML innebär detta att podSelector och den som står framför namespaceSelector hör ihop med samma lista. Därför kombineras de med logiskt OCH.

Att lägga till ett bindestreck framför podSelector kommer att leda till att ett nytt listobjekt skapas, som kommer att kombineras med det föregående namespaceSelector med hjälp av logiskt ELLER.

För att välja poddar med en specifik etikett i alla namnrymder, skriv en tom namespaceSelector:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: database.postgres
  namespace: database
spec:
  podSelector:
    matchLabels:
      app: postgres
  ingress:
  - from:
    - namespaceSelector: {}
      podSelector:
        matchLabels:
          app: admin
  policyTypes:
  - Ingress

Introduktion till Kubernetes nätverkspolicyer för säkerhetsspecialister

Flera etiketter kombineras med OCH

Brandväggsregler med flera objekt (värdar, nätverk, grupper) kombineras med hjälp av logiskt ELLER. Följande regel träder i kraft om paketets källa matchar Värd_1 ELLER Värd_2:

| Källa | Destination | Tjänst | Åtgärd |
| ----------------------------------------|
| Värd_1 | Subnät_A    | HTTPS   | Tillåt  |
| Värd_2 |             |         |        |
| ----------------------------------------|

Å andra sidan kombineras olika etiketter i Kubernetes med logiskt OCH. Till exempel kommer följande regel att välja poddar som har båda etiketterna podSelector eller namespaceSelector roll=db version=v2 Och podSelector: matchLabels: roll: db version: v2:

Samma logik gäller för alla typer av operatörer: policy målselectors, podselectors och namnrymdselectors.

Subnät och IP-adresser (IPBlocks)

För nätverkssegmentering använder brandväggar VLAN, IP-adresser och subnät.

I Kubernetes tilldelas IP-adresser till poddar automatiskt och kan ändras ofta, därför används etiketter för att välja poddar och namnrymder i nätverkspolicys.

Subnät (

ipBlocks) används för att styra inkommande (ingress) eller utgående (egress) externa (North-South) anslutningar. Till exempel öppnar denna policy för alla poddar i namnrymdenåtkomst till Googles DNS-tjänst: default apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: egress-dns namespace: default spec: podSelector: {} policyTypes: - Egress egress: - to: - ipBlock: cidr: 8.8.8.8/32 ports: - protocol: UDP port: 53

En tom podselector i det här exemplet innebär "välj alla poddar i namnrymden".

Introduktion till Kubernetes nätverkspolicyer för säkerhetsspecialister

Denna policy öppnar endast åtkomst till 8.8.8.8; åtkomst till någon annan IP är förbjuden. Således blockerar du i praktiken åtkomst till den interna DNS-tjänsten i Kubernetes. Om du ändå vill öppna den, ange detta explicit.

Vanligtvis

podSelectors ) används för att styra inkommande (ingress) eller utgående (egress) externa (North-South) anslutningar. Till exempel öppnar denna policy för alla poddar i namnrymden och är ömsesidigt uteslutande, eftersom interna IP-adresser för poddar inte används i . Genom att ange ) används för att styra inkommande (ingress) eller utgående (egress) externa (North-South) anslutningar. Till exempel öppnar denna policy för alla poddar i namnrymdeninterna IP-adresser för poddar interna IP för poddar, du kommer faktiskt att tillåta anslutningar till/från poddar med dessa adresser. I praktiken kommer du inte att veta vilken IP-adress som ska användas, därför bör de inte användas för att välja poddar.

Som ett motexempel inkluderar följande policy alla IP-adresser och tillåter därför åtkomst till alla andra poddar:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: egress-any
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Egress
  egress:
  - to:
    - ipBlock:
        cidr: 0.0.0.0/0

Introduktion till Kubernetes nätverkspolicyer för säkerhetsspecialister

Du kan öppna åtkomst endast till externa IP-adresser, genom att utesluta interna IP-adresser från poddar. Till exempel, om ditt pods nätverk är 10.16.0.0/14:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: egress-any
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Egress
  egress:
  - to:
    - ipBlock:
        cidr: 0.0.0.0/0
        except:
        - 10.16.0.0/14

Introduktion till Kubernetes nätverkspolicyer för säkerhetsspecialister

Portar och protokoll

Vanligtvis lyssnar poddar på en port. Det innebär att du enkelt kan välja att inte ange portnummer i policys och lämna allt som standard. Men det rekommenderas att göra policys så restriktiva som möjligt, så i vissa fall kan det vara bra att ange portar:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.postgres
  namespace: default
spec:
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: indexer
    - podSelector:
        matchLabels:
          app: admin
    ports:             # < < <
      - port: 443      # < < <
        protocol: TCP  # < < <
      - port: 80       # < < <
        protocol: TCP  # < < <
  podSelector:
    matchLabels:
      app: postgres
  policyTypes:
  - Ingress

Introduktion till Kubernetes nätverkspolicyer för säkerhetsspecialister

Lägg märke till att selektorn ports tillämpas på alla element i blocket till eller från, där det ligger. För att ange olika portar för olika uppsättningar av element, dela upp ingress eller egress i flera underavsnitt med till eller från och ange dina portar i varje:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.postgres
  namespace: default
spec:
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: indexer
    ports:             # < < <
     - port: 443       # < < <
       protocol: TCP   # < < <
  - from:
    - podSelector:
        matchLabels:
          app: admin
    ports:             # < < <
     - port: 80        # < < <
       protocol: TCP   # < < <
  podSelector:
    matchLabels:
      app: postgres
  policyTypes:
  - Ingress

Introduktion till Kubernetes nätverkspolicyer för säkerhetsspecialister

Standardporternas arbete:

  • Om du helt hoppar över portdefinitionerna (ports), betyder det alla protokoll och alla portar;
  • Om du hoppar över protokolldefinitionen (protocol), betyder det TCP;
  • Om du hoppar över portdefinitionen (port), betyder det alla portar.

Bästa praxis: förlita dig inte på standardvärden, utan ange vad du behöver tydligt.

Observera att du måste använda podarnas portar, inte tjänsternas (mer om detta i nästa stycke).

Är policyer definierade för poddar eller tjänster?

Normalt kommunicerar poddar i Kubernetes med varandra genom en tjänst — en virtuell belastningsbalanserare som dirigerar trafik till poddar som implementerar tjänsten. Man kan tro att nätverkspolicyer kontrollerar åtkomst till tjänster, men så är det inte. Nätverkspolicyer i Kubernetes fungerar med podarnas portar, inte tjänsternas.

Till exempel, om en tjänst lyssnar på port 80, men dirigerar trafik till port 8080 för sina poddar, måste nätverkspolicyn specificera just 8080.

En sådan mekanism bör erkännas som suboptimal: om den interna strukturen för tjänsten (vars portar poddarna lyssnar på) ändras, måste nätverkspolicyerna uppdateras.

En ny arkitekturmetod som använder Service Mesh (till exempel, se om Istio nedan — övers. not.) löser detta problem.

Behöver man specificera både Ingress och Egress?

Det korta svaret — ja, för att pod A ska kunna kommunicera med pod B, måste det tillåtas att etablera en utgående anslutning (för detta måste en egress-policy konfigureras), och pod B måste kunna ta emot en ingående anslutning (för detta behövs, givetvis, en ingress-policy).

Men i praktiken kan man lita på den standardpolicy som tillåter anslutningar i en eller båda riktningarna.

Om en viss pod-ClickHouse-Ninja/Proton väljs av en eller flera egress-policyer, kommer de begränsningar som påförs att bestämmas av deras disjunktion. I så fall måste det uttryckligen tillåtas att ansluta till pod-destinationen. Om podden inte väljs av någon policy, är dess utgående (egress) trafik tillåten som standard.

På liknande sätt kommer en pod-destination, som valts av en eller flera ingress-policyer, att ha sina begränsningar bestämda av deras disjunktion. I detta fall måste det uttryckligen tillåtas att ta emot trafik från podden-källa. Om podden inte väljs av någon policy, är all ingående (ingress) trafik för den tillåten som standard.

Se avsnittet "Stateful eller Stateless" nedan.

Loggar

Nätverkspolicyer i Kubernetes kan inte logga trafik. Detta gör det svårt att avgöra om policyn fungerar korrekt och komplicerar analysen inom säkerhetsområdet avsevärt.

Kontroll av trafik till externa tjänster

Kubernetes-nätverkspolicyn tillåter inte att ange ett fullständigt domännamn (DNS) i egress-sektionerna. Detta medför betydande besvär när man försöker begränsa trafiken till externa adresser som saknar en fast IP-adress (som aws.com).

Verifiering av policy

Brandväggar kommer att varna dig eller till och med vägra att acceptera en felaktig policy. Kubernetes genomför också viss verifiering. När nätverkspolicyn anges via kubectl kan Kubernetes meddela att den är felaktig och vägra att ta emot den. I andra fall kommer Kubernetes att acceptera policyn och fylla i de saknade detaljerna. Dessa kan ses med kommandot:

kubernetes get networkpolicy  -o yaml

Tänk på att Kubernetes verifieringssystem inte är ofelbart och kan missa vissa typer av fel.

Genomförande

Kubernetes ansvarar inte för implementeringen av nätverkspolicys själv, utan är bara en API-gateway som lägger det tunga ansvaret för kontroll på det underliggande systemet kallat Container Networking Interface (CNI). Att ange policys i en Kubernetes-kluster utan att tilldela en motsvarande CNI är som att skapa policys på en brandvägg utan att installera dem på brandväggarna. Du måste själv säkerställa att en tillfredsställande CNI finns, eller i fallet med Kubernetes-plattformar som är värd i molnet (med en lista över leverantörer kan du bekanta dig här — övers. anm.), aktivera nätverkspolicys som sätter upp CNI för dig.

Observera att Kubernetes inte kommer att varna dig om du ställer in en nätverkspolicy utan motsvarande underliggande CNI.

Stateful eller Stateless?

Alla CNI:er för Kubernetes som jag har stött på lagrar tillstånd (till exempel använder Calico Linux conntrack). Detta gör det möjligt för en pod att mottaga svar på en initierad TCP-anslutning utan att behöva återskapa den. Jag är dock inte medveten om någon Kubernetes-standard som garanterar lagring av tillstånd (statefulness).

Avancerad säkerhetspolicyhantering

Här är några sätt att öka effektiviteten av säkerhetspolicyernas genomförande i Kubernetes:

  1. Arkitekturmönstret Service Mesh använder sidecar-containrar för att säkerställa detaljerad telemetri och trafikövervakning på tjänstenivå. Ett exempel kan vara Istio.
  2. Vissa CNI-leverantörer har kompletterat sina verktyg så att de sträcker sig bortom Kubernetes nätverkspolicyer.
  3. Tufin Orca ger insyn och automatisering av Kubernetes nätverkspolicyer.

Tufin Orca-paketet hanterar Kubernetes nätverkspolicyer (och fungerar som källa för de skärmbilder som visas ovan).

Ytterligare information

Slutsats

Kubernetes nätverkspolicyer erbjuder en bra uppsättning verktyg för segmentering av kluster, men de är intuitivt svåra att förstå och har många subtiliteter. Jag anser att på grund av denna komplexitet innehåller politikerna i många befintliga kluster fel. Möjliga lösningar på detta problem är automatisering av policydefinitioner eller användning av andra segmenteringsverktyg.

Jag hoppas att denna handbok hjälper till att klargöra vissa frågor och lösa problem som du kan stöta på.

P.S. från översättaren

Läs även i vår blogg:

Källa: habr.com

Köp pålitlig webbhotell med DDoS-skydd, VPS VDS-servrar 🔥 Köp pålitlig webbhotell med DDoS-skydd, VPS VDS-servrar | ProHoster