Reverse Proxy : HAProxy, Traefik et la chaîne de sécurité

La chaine de reverse proxy

Chaque requete entrante traverse 5 couches avant d atteindre l application. Chaque couche a un role precis et des contraintes de configuration qui doivent etre alignees.

sequenceDiagram
    participant Client as Client Internet
    participant HAP as HAProxy<br/>VyOS Podman
    participant TFK as Traefik<br/>K3s Ingress
    participant VRN as Varnish<br/>Cache HTTP
    participant WAF as WAF nginx<br/>ModSecurity
    participant WP as WordPress<br/>PHP-FPM
    Client->>HAP: HTTPS (TLS 1.2/1.3)
    Note over HAP: TLS termination<br/>SNI routing via crt-list
    HAP->>TFK: HTTPS re-encrypted<br/>verify ca-file interne
    Note over TFK: HTTPRoute matching<br/>CrowdSec IP check
    TFK->>VRN: HTTP
    Note over VRN: Cache lookup
    alt HIT
        VRN-->>TFK: Reponse depuis cache
    else MISS
        VRN->>WAF: Forward request
        Note over WAF: ModSecurity CRS<br/>Inspection requete
        WAF->>WP: proxy_pass
        WP-->>WAF: Reponse
        WAF-->>VRN: Reponse
    end
    VRN-->>TFK: Reponse
    TFK-->>HAP: Reponse
    HAP-->>Client: HTTPS

HAProxy : terminaison TLS et routage SNI

HAProxy tourne en container Podman sur VyOS dans un reseau dedie. C est le premier point de contact pour le trafic entrant depuis Internet.

crt-list et SNI

Le mecanisme crt-list selectionne le certificat en fonction du SNI (Server Name Indication) envoye par le client :

# Format : chemin_pem [options] domaine [domaine2...]
/etc/haproxy/WWW/blog.pem blog.exemple.fr www.exemple.fr
/etc/haproxy/WWW/app.pem app.exemple.fr
/etc/haproxy/WWW/home.pem home.exemple.fr

Chaque ligne associe un fichier PEM (certificat + cle privee concatenes) a un ou plusieurs domaines.

Frontend ACL pattern

frontend ft_https
    bind *:443 ssl crt-list /etc/haproxy/WWW.crt_list alpn h2,http/1.1
    mode http

    # Normalisation du Host header
    http-request set-var(txn.txnhost) hdr(host),lower,regsub(:[0-9]+$,"")

    # Routage par domaine
    acl host_blog var(txn.txnhost) -m str blog.exemple.fr
    acl host_app  var(txn.txnhost) -m str app.exemple.fr

    use_backend bk_traefik if host_blog
    use_backend bk_traefik if host_app

Le pattern var(txn.txnhost) normalise le header Host (minuscules, suppression du port) pour un matching fiable.

Re-encryption vers Traefik

backend bk_traefik
    mode http
    timeout connect 30s
    timeout server 600s
    timeout tunnel 3600s

    server traefik1 10.0.2.101:30443 ssl 
        verify required 
        ca-file /etc/ssl/internal-ca.crt 
        sni str(traefik.internal)

Le trafic entre HAProxy et Traefik est re-chiffre avec verification du certificat interne. Le sni str(traefik.internal) envoie un SNI fixe a Traefik (le routage HTTP se fait sur le header Host, pas le SNI TLS).

Pourquoi re-chiffrer ? Meme sur un reseau interne, le trafic en clair peut etre intercepte si un container est compromis. La re-encryption avec CA interne garantit l authenticite de Traefik.

Traefik : ingress K3s et CrowdSec

Traefik est le controleur d ingress natif de K3s.

HTTPRoute (Gateway API)

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: wordpress-route
spec:
  hostnames:
    - "blog.exemple.fr"
  rules:
    - backendRefs:
        - name: varnish-service
          port: 8080
      filters:
        - type: ExtensionRef
          extensionRef:
            kind: Middleware
            name: crowdsec-bouncer

CrowdSec middleware

Le middleware CrowdSec verifie l IP source contre une base de reputation. Les IPs connues comme malveillantes sont bloquees avant meme d atteindre Varnish ou le WAF.

Timeouts critiques

Traefik a des timeouts par defaut de 60s (non documente dans la config K3s). Pour les uploads volumineux (photos Immich, medias WordPress), les timeouts doivent etre augmentes :

additionalArguments:
  - "--entryPoints.websecure.transport.respondingTimeouts.readTimeout=600s"
  - "--entryPoints.websecure.transport.respondingTimeouts.writeTimeout=600s"

Varnish : cache HTTP

Varnish se place entre Traefik et le WAF. Les pages deja en cache sont servies directement (HIT) sans toucher PHP/MySQL. Les requetes non-cachees (MISS) sont forwarded au WAF puis a WordPress.

Voir l article dedie : Varnish : cache et routage VCL

Alignement des timeouts

Tous les timeouts de la chaine doivent etre alignes. Un timeout plus court en amont coupe la connexion mid-upload et genere des erreurs 502/504.

Couche Parametre Valeur
HAProxy frontend timeout client 600s
HAProxy backend timeout server 600s
HAProxy backend timeout tunnel 3600s (WebSocket)
Traefik readTimeout 600s
Traefik writeTimeout 600s
WAF nginx proxy_read_timeout 600s
WAF nginx proxy_send_timeout 600s
Backend nginx proxy_read_timeout 600s

Mecanisme de panne : timeout court en amont, connexion coupee mid-upload, WAF recoit un body tronque, backend retourne 400 Bad Request, Traefik voit la coupure et renvoie 502.

Gotchas

PEM manquant dans la crt-list : HAProxy refuse categoriquement de demarrer si un fichier PEM reference dans la crt-list n existe pas. Impact : TOUS les sites down (pas seulement le nouveau domaine). C est pourquoi le certificat doit etre genere et verifie AVANT de modifier la crt-list.

WebSocket : les connexions upgradeees (Socket.IO, WebSocket) necessitent timeout tunnel 3600s dans HAProxy. Sans ca, les connexions longues sont coupees apres timeout server.

ConfigMap stale : les ConfigMaps montes avec subPath dans K3s sont figes au moment de la creation du pod. Modifier un ConfigMap ne met PAS a jour le fichier dans le pod -- un rollout restart est obligatoire.

Varnish probe : le probe backend doit utiliser /healthcheck (pas /). WordPress retourne 301 sur / ce qui fait echouer le probe et marque le backend comme sick.


Liens

Articles connexes


Commentaires

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur la façon dont les données de vos commentaires sont traitées.