Network Security #

Secara default, setiap Pod di Kubernetes bisa berkomunikasi dengan Pod lain tanpa batasan — tidak ada firewall, tidak ada enkripsi, tidak ada autentikasi. Ini adalah model yang sangat permisif yang bisa dieksploitasi jika salah satu Pod di-compromise. Network security di Kubernetes melibatkan beberapa lapisan: NetworkPolicy untuk kontrol akses, mTLS untuk enkripsi dan autentikasi, dan pengamanan endpoint yang mungkin diekspos.

Prinsip Zero-Trust Networking #

Zero-trust berarti tidak ada traffic yang dipercaya secara default — setiap koneksi harus diizinkan secara eksplisit:

Model default Kubernetes (TIDAK aman untuk produksi):
  Semua → Semua (tidak ada batasan)

Model zero-trust:
  Default: semua traffic diblokir
  Exceptions eksplisit: hanya izinkan traffic yang benar-benar dibutuhkan

Implementasi di Kubernetes:
  1. NetworkPolicy: kontrol layer 4 (IP/port)
  2. mTLS via service mesh: kontrol layer 7 (identitas service)

Implementasi Default-Deny per Namespace #

Langkah pertama: blokir semua traffic, lalu buka secara selektif.

# Default deny semua ingress dan egress di namespace production
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
  namespace: production
spec:
  podSelector: {}         # berlaku untuk semua Pod
  policyTypes:
  - Ingress
  - Egress

---
# Selalu izinkan DNS (wajib untuk semua namespace)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-dns
  namespace: production
spec:
  podSelector: {}
  policyTypes:
  - Egress
  egress:
  - to:
    - namespaceSelector:
        matchLabels:
          kubernetes.io/metadata.name: kube-system
    ports:
    - port: 53
      protocol: UDP
    - port: 53
      protocol: TCP

Isolasi Antar Namespace #

Secara default, Pod di namespace yang berbeda bisa saling berkomunikasi. Untuk isolasi multi-tenant:

# Hanya izinkan traffic dari namespace yang sama
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: same-namespace-only
  namespace: production
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector: {}     # Pod manapun...
      namespaceSelector:  # ...tapi hanya dari namespace ini (namespaceSelector kosong = namespace saat ini)
        matchLabels:
          kubernetes.io/metadata.name: production

---
# Izinkan juga dari namespace monitoring (untuk Prometheus scraping)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-from-monitoring
  namespace: production
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          kubernetes.io/metadata.name: monitoring
      podSelector:
        matchLabels:
          app: prometheus
    ports:
    - port: 9090    # metrics port

Mencegah Akses ke Metadata Cloud Provider #

Metadata endpoint cloud provider (AWS: 169.254.169.254, GCP: metadata.google.internal) sering digunakan penyerang untuk mencuri IAM credentials. Blokir akses ini dari Pod:

# Blokir akses ke AWS metadata endpoint dari semua Pod
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: block-metadata-endpoint
  namespace: production
spec:
  podSelector: {}
  policyTypes:
  - Egress
  egress:
  - to:
    - ipBlock:
        cidr: 0.0.0.0/0
        except:
        - 169.254.169.254/32    # AWS metadata endpoint
        - 169.254.170.2/32      # AWS ECS metadata endpoint
        # GCP: 169.254.169.254 sudah ter-cover
        # Azure: 169.254.169.254 sudah ter-cover

mTLS dengan Service Mesh #

NetworkPolicy bekerja di layer 4 (IP/port) — ia tidak bisa membedakan apakah koneksi dari Pod A yang legitimate atau dari Pod yang di-compromise. mTLS menambahkan autentikasi kriptografis di setiap koneksi.

Tanpa mTLS:
  Pod A → Pod B (tidak ada enkripsi, tidak ada autentikasi)
  Siapapun yang bisa intercept network bisa baca traffic
  Pod yang di-compromise bisa pura-pura jadi service lain

Dengan mTLS (Istio/Cilium):
  Pod A (cert: service-a.production.svc.cluster.local)
    ─── TLS mutual auth + enkripsi ───
  Pod B (cert: service-b.production.svc.cluster.local)

  Pod B verifikasi bahwa koneksi benar-benar dari service-a
  Tidak ada yang bisa impersonate service-a tanpa certificate-nya
# Aktifkan mTLS strict di namespace (Istio)
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: default
  namespace: production
spec:
  mtls:
    mode: STRICT    # tolak semua koneksi non-mTLS

Hardening Ingress #

Ingress adalah entry point dari internet — perlu perlindungan tambahan:

metadata:
  annotations:
    # Rate limiting: max 100 req/detik per IP
    nginx.ingress.kubernetes.io/limit-rps: "100"
    nginx.ingress.kubernetes.io/limit-burst-multiplier: "5"

    # HSTS: paksa HTTPS selama 1 tahun
    nginx.ingress.kubernetes.io/hsts: "true"
    nginx.ingress.kubernetes.io/hsts-max-age: "31536000"
    nginx.ingress.kubernetes.io/hsts-include-subdomains: "true"

    # Redirect HTTP ke HTTPS
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    nginx.ingress.kubernetes.io/force-ssl-redirect: "true"

    # Security headers
    nginx.ingress.kubernetes.io/configuration-snippet: |
      more_set_headers "X-Frame-Options: DENY";
      more_set_headers "X-Content-Type-Options: nosniff";
      more_set_headers "Referrer-Policy: strict-origin-when-cross-origin";
      more_set_headers "Permissions-Policy: geolocation=(), microphone=()";      

    # Ukuran request maksimal (cegah large payload attack)
    nginx.ingress.kubernetes.io/proxy-body-size: "10m"

    # Timeout
    nginx.ingress.kubernetes.io/proxy-read-timeout: "60"
    nginx.ingress.kubernetes.io/proxy-connect-timeout: "10"

Enkripsi Traffic Antar Node (CNI Level) #

Untuk cluster yang membutuhkan enkripsi di level transport antar node:

# Calico dengan WireGuard encryption
kubectl patch felixconfiguration default --type=merge \
  -p '{"spec":{"wireguardEnabled":true}}'

# Cilium dengan WireGuard encryption
helm upgrade cilium cilium/cilium \
  --set encryption.enabled=true \
  --set encryption.type=wireguard

Enkripsi di level CNI melindungi semua traffic antar node — termasuk traffic yang tidak menggunakan mTLS. Overhead CPU biasanya 5-15%.


Ringkasan #

  • Default-deny dulu, buka yang perlu — mulai dengan NetworkPolicy yang blokir semua, lalu tambahkan policy yang membuka traffic spesifik; lebih mudah daripada menutup satu per satu.
  • Selalu sertakan allow-dns — default-deny egress tanpa exception DNS membuat semua name resolution gagal; ini kesalahan paling umum.
  • Blokir metadata endpoint cloud provider — 169.254.169.254 adalah target umum untuk credential theft; blokir via ipBlock.except di NetworkPolicy egress.
  • mTLS untuk autentikasi service-to-service — NetworkPolicy mengontrol IP/port, tapi tidak memvalidasi identitas; mTLS memastikan hanya service yang terotorisasi yang bisa connect.
  • Ingress perlu rate limiting dan security headers — batas request per IP, HSTS, redirect HTTP→HTTPS, dan security headers adalah konfigurasi minimum untuk production.
  • WireGuard encryption di CNI untuk enkripsi menyeluruh — Calico dan Cilium mendukung enkripsi traffic antar node via WireGuard; melindungi traffic yang tidak di-cover mTLS.

← Sebelumnya: Pod Security   Berikutnya: Supply Chain Security →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact