Zum Inhalt springen

Services, Wiki-Artikel und Blog-Beiträge durchsuchen

↑↓NavigierenEnterÖffnenESCSchließen
Kubernetes Network Policies: Mikrosegmentierung im Cluster - Container-Sicherheit und Orchestrierung
Cloud Security

Kubernetes Network Policies: Mikrosegmentierung im Cluster

Kubernetes Network Policies: Ingress/Egress-Regeln, Default-Deny, namespace-basierte Isolation und Service-Mesh-Alternativen mit Istio/Cilium.

Vincent Heinen Abteilungsleiter Offensive Services
10 Min. Lesezeit
OSCP+ OSCP OSWP OSWA

TL;DR

Kubernetes Network Policies implementieren das Least-Privilege-Prinzip auf Netzwerkebene im Cluster. Ohne Policies können alle Pods miteinander kommunizieren, was bei einem kompromittierten Pod zum Einfallstor für alle anderen wird. Policies sind Whitelist-basiert und additiv: ein Pod ohne Policy hat keine Einschränkung, ein selektierter Pod wird auf alle nicht explizit erlaubten Verbindungen blockiert. Praxisempfehlungen sind Default-Deny-Policies pro Namespace, explizite Ingress- und Egress-Regeln sowie Service-Mesh-Alternativen wie Istio oder Cilium für erweitertes Traffic-Management.

Diese Zusammenfassung wurde KI-gestützt erstellt (EU AI Act Art. 50).

Inhaltsverzeichnis (5 Abschnitte)

In einem Standard-Kubernetes-Cluster ohne Network Policies können alle Pods miteinander kommunizieren - jeder kann jeden erreichen. Das ist für die Entwicklung praktisch, aber sicherheitstechnisch ein Problem: ein kompromittierter Pod kann alle anderen Pods im Cluster angreifen. Network Policies implementieren Mikrosegmentierung und das Least-Privilege-Prinzip auf Netzwerkebene.

Grundkonzept

Namespace production mit drei Pods: frontend (Port 3000), backend (Port 8080), database (Port 5432).

OHNE Network Policies sind alle Verbindungen erlaubt:

frontend <-> backend <-> database  (gewünscht)
frontend -> database               (UNERWÜNSCHT! Frontend sollte DB nicht erreichen)
database -> frontend               (UNERWÜNSCHT! DB sollte keine ausgehenden Connections machen)

Ein kompromittiertes Frontend kann direkt auf database:5432 zugreifen - keine zusätzliche Hürde.

MIT Network Policies (richtig konfiguriert):

frontend -> backend (8080): ERLAUBT
frontend -> database (5432): BLOCKIERT
backend -> database (5432): ERLAUBT
database -> irgendwo: BLOCKIERT

Network Policy Grundregeln:

  • Policies sind ADDITIV: eine Allow-Regel reicht für Erlaubnis
  • Policies sind WHITELIST-basiert: wenn eine Policy einen Pod selektiert, wird ALLES andere blockiert was nicht explizit erlaubt ist
  • Kein Policy = kein Restriction (alle Verbindungen erlaubt!)
  • Default-Deny: muss explizit durch Policy implementiert werden

Network Policy Syntax

Grundstruktur:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: my-policy
  namespace: production
spec:
  podSelector:         # Auf welche Pods wird diese Policy angewendet?
    matchLabels:
      app: backend
  policyTypes:         # Was wird spezifiziert?
    - Ingress          # Eingehender Traffic
    - Egress           # Ausgehender Traffic
  ingress:             # Eingehende Traffic-Regeln
    - from:
        - podSelector:
            matchLabels:
              app: frontend
      ports:
        - protocol: TCP
          port: 8080
  egress:              # Ausgehende Traffic-Regeln
    - to:
        - podSelector:
            matchLabels:
              app: database
      ports:
        - protocol: TCP
          port: 5432

Selektoren im Detail:

podSelector (Pods im gleichen Namespace):

- from:
    - podSelector:
        matchLabels:
          app: frontend

namespaceSelector (Pods aus anderem Namespace):

- from:
    - namespaceSelector:
        matchLabels:
          kubernetes.io/metadata.name: monitoring

Kombination (Pods in spezifischem Namespace, UND-Verknüpfung durch gleichen Listeneintrag - zwei getrennte Einträge wären ODER!):

- from:
    - namespaceSelector:
        matchLabels:
          environment: production
      podSelector:      # UND-Verknüpfung (gleicher Listeneintrag!)
        matchLabels:
          app: prometheus

ipBlock (externe IP-Bereiche):

- from:
    - ipBlock:
        cidr: 10.0.0.0/8
        except:
          - 10.1.1.0/24  # Diese Range ausschließen

Praktische Policy-Patterns

Pattern 1 - Default-Deny-All (Basis für jede sichere Konfiguration):

# Kein Traffic erlaubt zu diesem Pod (Ingress + Egress)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
  namespace: production
spec:
  podSelector: {}  # Leerer Selektor = ALLE Pods im Namespace
  policyTypes:
    - Ingress
    - Egress
  # Keine ingress/egress Regeln = alles verboten!
---
# Dann gezielt erlauben:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-backend-to-db
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: database
  policyTypes:
    - Ingress
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app: backend
      ports:
        - port: 5432

Pattern 2 - Namespace-Isolation (empfohlen für alle Namespaces):

# Kein Ingress aus anderen Namespaces
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-from-other-namespaces
  namespace: production
spec:
  podSelector: {}
  policyTypes:
    - Ingress
  ingress:
    - from:
        - podSelector: {}  # Nur Pods im GLEICHEN Namespace
        # Kein namespaceSelector = nur gleicher Namespace!

Pattern 3 - Zugriff nur vom Monitoring-Namespace:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-prometheus-scraping
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: backend
  policyTypes:
    - Ingress
  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              purpose: monitoring
          podSelector:
            matchLabels:
              app: prometheus
      ports:
        - port: 9090  # Metrics-Port

Pattern 4 - DNS-Egress erlauben (häufig vergessen - Pods brauchen DNS-Zugriff!):

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-dns-egress
  namespace: production
spec:
  podSelector: {}  # Alle Pods
  policyTypes:
    - Egress
  egress:
    - ports:
        - port: 53
          protocol: UDP
        - port: 53
          protocol: TCP
    # Gleichzeitig kube-dns/CoreDNS erlauben:
    - to:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: kube-system
          podSelector:
            matchLabels:
              k8s-app: kube-dns

Pattern 5 - Internet-Egress für spezifische Pods:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-external-api
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: api-client
  policyTypes:
    - Egress
  egress:
    - to:
        - ipBlock:
            cidr: 0.0.0.0/0    # Ganzes Internet
            except:
              - 10.0.0.0/8     # Private Ranges ausschließen
              - 172.16.0.0/12  # (Kubernetes-interne Isolation)
              - 192.168.0.0/16
      ports:
        - port: 443
        - port: 80

CNI-Plugins und Service Mesh

Nicht alle CNI-Plugins unterstützen Network Policies!

PluginNetwork Policy Support
FlannelKEIN Support (nur Layer-3-Routing)
CalicoFull Support + erweiterte Features
CiliumeBPF-basiert, L7-Policies, beste Performance
WeaveNetSupport
CanalFlannel + Calico-Policy-Enforcement

Calico NetworkPolicy (erweiterte Syntax, erlaubt mehr als Standard-K8s-Policies):

apiVersion: projectcalico.org/v3
kind: NetworkPolicy
metadata:
  name: allow-https-only
spec:
  selector: app == 'frontend'
  types:
    - Egress
  egress:
    - action: Allow
      protocol: TCP
      destination:
        ports: [443]
    - action: Deny  # Explizites Deny!

Cilium (eBPF-basierte L7-Policies - nur GET/POST auf spezifische Pfade, Layer-7-Filtering ohne Service Mesh!):

apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: api-policy
spec:
  endpointSelector:
    matchLabels:
      app: backend
  ingress:
    - fromEndpoints:
        - matchLabels:
            app: frontend
      toPorts:
        - ports:
            - port: "8080"
              protocol: TCP
          rules:
            http:
              - method: "GET"
                path: "/api/v1/.*"
              - method: "POST"
                path: "/api/v1/orders"

Service Mesh - Istio AuthorizationPolicy (ergänzend zu K8s Network Policies):

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: backend-policy
spec:
  selector:
    matchLabels:
      app: backend
  action: ALLOW
  rules:
  - from:
    - source:
        principals: ["cluster.local/ns/prod/sa/frontend-sa"]
    to:
    - operation:
        methods: ["GET", "POST"]
        paths: ["/api/*"]

Network Policies vs. Service Mesh: Network Policies arbeiten auf IP/Port-Level (Layer 3/4), Service Mesh bietet mTLS, L7-Filtering, RBAC und Observability. Beste Sicherheit: beides kombinieren!

Troubleshooting und Best Practices

Fehler 1 - ODER statt UND bei Selektoren:

FALSCH (OR-Semantik - zwei getrennte Listeneinträge):

ingress:
  - from:
      - podSelector:         # Regel 1: Pods mit app=api
          matchLabels:
            app: api
      - namespaceSelector:   # Regel 2: ODER alle aus monitoring-NS
          matchLabels:
            purpose: monitoring

RICHTIG (AND-Semantik - gleicher Listeneintrag):

ingress:
  - from:
      - podSelector:         # Pods mit app=api
          matchLabels:
            app: api
        namespaceSelector:   # UND im monitoring-NS
          matchLabels:
            purpose: monitoring

Fehler 2 - DNS vergessen: Default-Deny-Egress blockiert DNS-Auflösung - App kann Service-Names nicht auflösen. IMMER DNS-Egress (Port 53 UDP+TCP) erlauben!

Fehler 3 - Kube-System vergessen: Manche K8s-interne Services im kube-system Namespace (Health-Checks, Metrics, Admission Webhooks) brauchen Zugriff. Nach Policy-Deployment Cluster-Health prüfen!

Fehler 4 - NodePort/LoadBalancer vergessen: Externe Anfragen kommen von Node-IP (andere IP als Pod-IP) - ipBlock mit Cluster-IP-Range nötig für externe Anfragen.

Debugging:

# Alle Network Policies im Namespace:
kubectl get networkpolicies -n production
kubectl describe networkpolicy my-policy -n production

# Pod-Konnektivität testen (wenn blockiert: Connection refused oder timeout):
kubectl exec -n production frontend-pod -- curl -v backend-service:8080/api/health

# Cilium: Netzwerkflüsse beobachten:
cilium monitor --type drop   # Zeigt geblockte Verbindungen!
cilium monitor --type trace  # Alle Verbindungen

# Calico: Flow-Logs aktivieren (kommerzielles Feature)
# Netreap / Retina (Microsoft): eBPF-basiertes Network-Monitoring

Verifikation der Policy:

kubectl auth can-i --list --as=system:serviceaccount:prod:default
# Zeigt ob Service Account erwartete Rechte hat

# Tool: kubectl-np-viewer (Visualisierung):
kubectl np-viewer -n production

Network Policies sind ein unverzichtbares Sicherheitselement in Kubernetes-Produktionsclustern. Der Aufwand für ihre Implementierung zahlt sich durch erheblich reduziertes Lateral-Movement-Risiko aus: ein kompromittierter Pod kann nicht mehr alle anderen Pods und Services erreichen. AWARE7 überprüft Kubernetes-Cluster-Konfigurationen auf fehlende oder zu permissive Network Policies als Teil von Cloud-Security-Assessments.

Kubernetes Security Assessment | Cloud Security Beratung

Nächster Schritt

Unsere zertifizierten Sicherheitsexperten beraten Sie zu den Themen aus diesem Artikel, unverbindlich und kostenlos.

Kostenlos · 30 Minuten · Unverbindlich

Artikel teilen

Über den Autor

Vincent Heinen
Vincent Heinen

Abteilungsleiter Offensive Services

E-Mail

M.Sc. IT-Sicherheit mit über 5 Jahren Erfahrung in offensiver Sicherheitsanalyse. Leitet die Durchführung von Penetrationstests mit Spezialisierung auf Web-Applikationen, Netzwerk-Infrastruktur, Reverse Engineering und Hardware-Sicherheit. Verantwortlich für mehrere Responsible Disclosures.

OSCP+ OSCP OSWP OSWA
Zertifiziert ISO 27001ISO 9001AZAV

Rufen Sie uns an

Mo-Fr, 8:00-17:00 Uhr - persönlich und unverbindlich.

0209 8830 6764
Jetzt anrufen