Korzen
Bot Protection

Kubernetes

Bot Protection da un'app su Kubernetes: l'API key come Secret, l'IP del visitatore attraverso il load balancer e ingress-nginx, e l'egress.

Kubernetes cambia tre cose nella chiamata dal tuo server: dove sta l'API key, come l'indirizzo del visitatore sopravvive al load balancer e all'ingress, e se il pod può raggiungere korzen.dev. La chiamata in sé è quella del tuo framework: prendila dalla guida del tuo stack.

La chiave

Tieni l'API key in un Secret, mai nell'immagine o in una ConfigMap, e passala al container come variabile d'ambiente:

kubectl create secret generic korzen --from-literal=api-key=ak_your_key
# deployment.yaml, in your app's container
env:
  - name: KORZEN_API_KEY
    valueFrom:
      secretKeyRef:
        name: korzen
        key: api-key

L'IP del visitatore

Di default un load balancer cloud nasconde il visitatore dietro il proprio indirizzo, e lo stesso fa l'ingress. Due impostazioni lo preservano: externalTrafficPolicy: Local sul Service dell'ingress controller, e ingress-nginx che si fida dell'header aggiunto dal load balancer. La tua applicazione legge poi X-Real-IP, o l'ultima voce di X-Forwarded-For, che imposta ingress-nginx; dietro Cloudflare, CF-Connecting-IP.

# The ingress controller's Service: keep the visitor's address on the way in.
apiVersion: v1
kind: Service
metadata:
  name: ingress-nginx-controller
  namespace: ingress-nginx
spec:
  type: LoadBalancer
  externalTrafficPolicy: Local
# ingress-nginx's ConfigMap: trust the load balancer in front, pass the address on.
apiVersion: v1
kind: ConfigMap
metadata:
  name: ingress-nginx-controller
  namespace: ingress-nginx
data:
  use-forwarded-headers: "true"     # only if a load balancer you control is in front
  compute-full-forwarded-for: "true"
  # use-proxy-protocol: "true"      # instead, if your cloud's load balancer speaks PROXY protocol

Egress

Se il cluster blocca di default il traffico in uscita da un namespace, il pod deve poter raggiungere la porta 443:

# Only if your cluster blocks egress by default: let the app reach HTTPS.
# A plain NetworkPolicy matches addresses, not names, and korzen.dev answers from
# Cloudflare's ranges; with Cilium, an FQDN rule can name korzen.dev itself.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: app-egress-https
spec:
  podSelector:
    matchLabels:
      app: shop
  policyTypes: [Egress]
  egress:
    - ports:
        - port: 443
          protocol: TCP
    - ports:
        - port: 53
          protocol: UDP

In esercizio

  • Un solo client HTTP per pod, tenuto aperto; ogni replica apre la propria connessione, e va bene così.
  • Non far mai dipendere una readiness o liveness probe da Bot Protection: quando è lento, i pod devono restare in servizio e applicare il fail-open.
  • Il timeout del tuo SDK si calcola da dove gira il cluster: un cluster nella costa ovest degli USA ha bisogno di circa 300 ms.

Errori comuni

  • L'indirizzo dell'ingress inviato come quello del visitatore: ogni decisione condivide allora un solo IP, e Bot Protection vede un unico visitatore molto indaffarato.
  • use-forwarded-headers attivo senza niente davanti che tu controlli: un visitatore scrive X-Forwarded-For e si sceglie l'indirizzo.
  • La chiave in una ConfigMap o inclusa nell'immagine, dove la vede chiunque abbia accesso in lettura al namespace o al registry.