Zum Inhalt

Cloud-Nativer Edge-Router: Traefik v3 Dynamische Discovery, Socket-Proxy & Middleware-Ketten

Erstellt: 06.11.2026 Aktualisiert: 06.11.2026

Management Summary: Die manuelle Pflege statischer Reverse-Proxy-Dateien in dynamischen Container-Umgebungen führt regelmäßig zu Konfigurationsabweichungen und Neustart-Latenzen. Dieser Leitfaden beschreibt das Produktiv-Deployment von Traefik Proxy v3. Durch labelbasierte Erkennung über einen schreibgeschützten Docker Socket Proxy, modular verkettbare Middleware-Pipelines (Rate Limiting, ForwardAuth, Security-Header), TCP/UDP-SNI-Routing (HostSNI) und automatisiertes ACME-DNS-01-Zertifikatsmanagement entfällt jeglicher manueller Eingriff.

  • Reload-Freie Dynamische Discovery


    Erkennt Container, Health-Checks und Routing-Regeln in Echtzeit über Docker-Labels, ohne Prozesse neu zu starten oder Sockets zu trennen.

  • Docker-Socket-Isolation


    Beseitigt das Sicherheitsrisiko von /var/run/docker.sock durch Vorschalten eines gehärteten tecnativa/docker-socket-proxy (CONTAINERS=1).

  • Modulare Middleware-Ketten


    Verkettet Token-Bucket-Rate-Limiter, HSTS-Header, IP-Allowlists und Authelia-ForwardAuth über wiederverwendbare Label-Referenzen.

  • Einheitliches HTTP/3, TCP & UDP SNI


    Routet HTTP/3 (QUIC), reines TLS-Passthrough für TCP-Verbindungen (PostgreSQL, Redis, SMTPS) und UDP-Traffic über zentrale EntryPoints.


1. Architektur: EntryPoints, Routers, Middlewares & Services

Traefik v3 trennt statische Startup-Infrastruktur (EntryPoints und Providers) strikt von der dynamischen Laufzeitlogik (Routers, Middlewares und Services):

%%{init: {'flowchart': {'wrappingWidth': 600, 'subGraphTitleMargin': {'top': 15, 'bottom': 15}}}}%%
flowchart TB
    subgraph EdgeEntry["EntryPoints (Ports 80 / 443)"]
        Web["web (:80)<br/>Permanenter 308 -> websecure"]
        WebSecure["websecure (:443 TCP/UDP)<br/>TLS 1.3 + HTTP/3 + ACME"]
    end

    subgraph TraefikPlane["Traefik v3 Dynamische Pipeline"]
        Router["Router Rule Match<br/>Host(`app.nejat-hakan.de`)"]
        MWChain["Middleware Chain<br/>RateLimit -> Auth -> Headers"]
        Service["LoadBalancer Service<br/>HealthCheck + Sticky Cookie"]
    end

    subgraph ControlDiscovery["Isolierte Control Plane"]
        SockProxy["Docker Socket Proxy<br/>NUR GET /containers/json"]
    end

    subgraph BackendTier["Container Backends"]
        App1["App Replikat 1<br/>172.29.0.12:8080"]
        App2["App Replikat 2<br/>172.29.0.13:8080"]
    end

    Web -.->|"308 Weiterleitung"| WebSecure
    WebSecure --> Router
    SockProxy -.->|"Events auslesen"| Router
    Router --> MWChain
    MWChain --> Service
    Service --> App1
    Service --> App2

Warum ein Docker Socket Proxy zwingend erforderlich ist

Das direkte Einbinden von /var/run/docker.sock in einen öffentlich erreichbaren Reverse-Proxy-Container birgt erhebliche Risiken: Gelingt Angreifern die Ausführung von Schadcode im Proxy, können sie über die Docker-API (POST /containers/create) privilegierte Container mit Zugriff auf das Host-Dateisystem starten. Durch Zwischenschalten des docker-socket-proxy im internen Netzwerk socket_net (ausschließlich GET auf Container-Informationen) kann Traefik selbst im Kompromittierungsfall keine Container manipulieren oder erzeugen.


2. Produktiv-Stack: Traefik v3 + Gehärteter Socket Proxy

/opt/traefik/compose.yaml
services:
  socket-proxy:
    image: lscr.io/linuxserver/socket-proxy:latest
    container_name: traefik-socket-proxy
    restart: unless-stopped
    read_only: true
    tmpfs:
      - /run
    environment:
      CONTAINERS: 1
      NETWORKS: 1
      SERVICES: 1
      TASKS: 1
      POST: 0
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    networks:
      - socket_net

  traefik:
    image: traefik:v3.2
    container_name: traefik-edge
    restart: unless-stopped
    depends_on:
      - socket-proxy
    security_opt:
      - no-new-privileges:true
    ports:
      - "80:80/tcp"
      - "443:443/tcp"
      - "443:443/udp"
    environment:
      TZ: "Europe/Berlin"
      CF_DNS_API_TOKEN_FILE: "/run/secrets/cf_dns_token"
    volumes:
      - ./traefik.yaml:/etc/traefik/traefik.yaml:ro
      - ./dynamic:/etc/traefik/dynamic:ro
      - ./acme:/etc/traefik/acme:Z
    networks:
      - socket_net
      - traefik_proxy

networks:
  socket_net:
    internal: true
  traefik_proxy:
    external: true

3. Statische & Dynamische Konfigurationsdateien

/opt/traefik/traefik.yaml
global:
  checkNewVersion: false
  sendAnonymousUsage: false

api:
  dashboard: true
  insecure: false

entryPoints:
  web:
    address: ":80"
    http:
      redirections:
        entryPoint:
          to: websecure
          scheme: https
          permanent: true

  websecure:
    address: ":443"
    http3: {}
    http:
      tls:
        certResolver: letsencrypt
        domains:
          - main: "nejat-hakan.de"
            sans:
              - "*.nejat-hakan.de"
    transport:
      respondingTimeouts:
        readTimeout: 60s
        writeTimeout: 60s
        idleTimeout: 180s

providers:
  docker:
    endpoint: "tcp://socket-proxy:2375"
    exposedByDefault: false
    network: traefik_proxy
  file:
    directory: "/etc/traefik/dynamic"
    watch: true

certificatesResolvers:
  letsencrypt:
    acme:
      email: "hostmaster@nejat-hakan.de"
      storage: "/etc/traefik/acme/acme.json"
      keyType: "EC384"
      dnsChallenge:
        provider: cloudflare
        resolvers:
          - "1.1.1.1:53"
          - "9.9.9.9:53"

log:
  level: INFO
accessLog:
  format: json
  fields:
    headers:
      defaultMode: drop
      names:
        User-Agent: keep
        X-Forwarded-For: keep
/opt/traefik/dynamic/middlewares.yaml
tls:
  options:
    default:
      minVersion: VersionTLS12
      sniStrict: true
      curvePreferences:
        - X25519
        - CurveP384
      cipherSuites:
        - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
        - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
        - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
        - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256

http:
  middlewares:
    sec-headers:
      headers:
        stsSeconds: 63072000
        stsIncludeSubdomains: true
        stsPreload: true
        forceSTSHeader: true
        frameDeny: true
        contentTypeNosniff: true
        browserXssFilter: true
        referrerPolicy: "strict-origin-when-cross-origin"
        customResponseHeaders:
          Server: ""

    rate-limit-std:
      rateLimit:
        average: 100
        burst: 50
        period: 1s

    lan-whitelist:
      ipAllowList:
        sourceRange:
          - "192.168.10.0/24"
          - "10.88.0.0/24"

    # Zentrale Kette für öffentliche Dienste
    public-chain:
      chain:
        middlewares:
          - rate-limit-std
          - sec-headers

    # Zentrale Kette für interne Administrationsdienste
    internal-chain:
      chain:
        middlewares:
          - lan-whitelist
          - sec-headers

4. Backend-Container via Traefik v3 Labels anbinden

Mit exposedByDefault: false genügen vier prägnante Labels zur vollständigen Absicherung eines Dienstes:

Beispiel-Backend-Onboarding mit Traefik v3 Labels
services:
  whoami:
    image: traefik/whoami:latest
    container_name: whoami-test
    networks:
      - traefik_proxy
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.whoami.rule=Host(`whoami.nejat-hakan.de`)"
      - "traefik.http.routers.whoami.entrypoints=websecure"
      - "traefik.http.routers.whoami.middlewares=internal-chain@file"
      - "traefik.http.services.whoami.loadbalancer.server.port=80"

TCP-SNI-Passthrough (PostgreSQL / Mail / TLS-Backends)

Traefik kann verschlüsselten TCP-Traffic direkt ohne Terminierung durchleiten (passthrough: true) oder TLS am Edge terminieren:

TCP Router in /opt/traefik/dynamic/tcp-routes.yaml
tcp:
  routers:
    postgres-tls:
      entryPoints:
        - websecure
      rule: "HostSNI(`db.lan.nejat-hakan.de`)"
      service: postgres-svc
      tls:
        passthrough: false

  services:
    postgres-svc:
      loadBalancer:
        servers:
          - address: "192.168.10.50:5432"

5. Verifikation & Diagnostik

Stellen Sie sicher, dass /opt/traefik/acme/acme.json vor dem Start die Dateirechte 0600 besitzt:

acme.json absichern & HTTP/3 + TLS 1.3 prüfen
# 1. Strikte Dateirechte für den ACME-Zertifikatsspeicher setzen
touch /opt/traefik/acme/acme.json
chmod 0600 /opt/traefik/acme/acme.json

# 2. HTTP/3 (Alt-Svc Header) und HSTS via curl validieren
curl -ILs https://whoami.nejat-hakan.de | grep -iE "strict-transport|alt-svc|http/"

# 3. Strukturierte JSON-Access-Logs auf Anfragen > 100ms filtern
docker logs traefik-edge 2>&1 | jq 'select(.Duration > 100000000)'