Trusted-Proxy-Auth

Sicherheitssensitives Feature. Dieser Modus delegiert die Authentifizierung vollständig an deinen Reverse-Proxy. Fehlkonfiguration kann dein Gateway unbefugtem Zugriff aussetzen. Lies diese Seite sorgfältig, bevor du ihn aktivierst.

Wann verwenden

Verwende den trusted-proxy-Auth-Modus, wenn:

  • Du OpenClaw hinter einem identitätsbewussten Proxy betreibst (Pomerium, Caddy + OAuth, nginx + oauth2-proxy, Traefik + Forward-Auth)
  • Dein Proxy die gesamte Authentifizierung übernimmt und die Benutzeridentität per Header weitergibt
  • Du dich in einer Kubernetes- oder Container-Umgebung befindest, in der der Proxy der einzige Weg zum Gateway ist
  • Du auf WebSocket-1008 unauthorized-Fehler stößt, weil Browser keine Tokens in WS-Payloads senden können

Wann NICHT verwenden

  • Wenn dein Proxy keine Benutzer authentifiziert (nur TLS-Terminator oder Load-Balancer)
  • Wenn es einen Weg zum Gateway gibt, der den Proxy umgeht (Firewall-Löcher, interner Netzwerkzugriff)
  • Wenn du unsicher bist, ob dein Proxy Forwarded-Header korrekt entfernt/überschreibt
  • Wenn du nur persönlichen Single-User-Zugriff brauchst (erwäge Tailscale Serve + Loopback für ein einfacheres Setup)

Funktionsweise

  1. Dein Reverse-Proxy authentifiziert Benutzer (OAuth, OIDC, SAML usw.)
  2. Der Proxy fügt einen Header mit der authentifizierten Benutzeridentität hinzu (z. B. x-forwarded-user: [email protected])
  3. OpenClaw prüft, ob die Anfrage von einer vertrauenswürdigen Proxy-IP kommt (konfiguriert in gateway.trustedProxies)
  4. OpenClaw extrahiert die Benutzeridentität aus dem konfigurierten Header
  5. Wenn alles stimmt, wird die Anfrage autorisiert

Control-UI-Pairing-Verhalten

Wenn gateway.auth.mode = "trusted-proxy" aktiv ist und die Anfrage die Trusted-Proxy-Prüfungen besteht, können Control-UI-WebSocket-Sessions ohne Device-Pairing-Identität verbinden.

Implikationen:

  • Pairing ist in diesem Modus nicht mehr das primäre Gate für Control-UI-Zugriff.
  • Die Auth-Policy deines Reverse-Proxys und allowUsers werden zur effektiven Zugriffskontrolle.
  • Halte den Gateway-Ingress auf vertrauenswürdige Proxy-IPs beschränkt (gateway.trustedProxies + Firewall).

Konfiguration

{
  gateway: {
    // loopback für Same-Host-Proxy-Setups; lan/custom für Remote-Proxy-Hosts verwenden
    bind: "loopback",

    // WICHTIG: Hier nur die IPs deines Proxys eintragen
    trustedProxies: ["10.0.0.1", "172.17.0.1"],

    auth: {
      mode: "trusted-proxy",
      trustedProxy: {
        // Header mit authentifizierter Benutzeridentität (erforderlich)
        userHeader: "x-forwarded-user",

        // Optional: Header, die vorhanden sein MÜSSEN (Proxy-Verifizierung)
        requiredHeaders: ["x-forwarded-proto", "x-forwarded-host"],

        // Optional: auf bestimmte Benutzer einschränken (leer = alle erlauben)
        allowUsers: ["[email protected]", "[email protected]"],
      },
    },
  },
}

Wenn gateway.bind auf loopback steht, nimm eine Loopback-Proxy-Adresse in gateway.trustedProxies auf (127.0.0.1, ::1 oder ein äquivalentes Loopback-CIDR).

Konfigurationsreferenz

FeldErforderlichBeschreibung
gateway.trustedProxiesJaArray von Proxy-IP-Adressen, denen vertraut wird. Anfragen von anderen IPs werden abgelehnt.
gateway.auth.modeJaMuss "trusted-proxy" sein
gateway.auth.trustedProxy.userHeaderJaHeader-Name mit der authentifizierten Benutzeridentität
gateway.auth.trustedProxy.requiredHeadersNeinZusätzliche Header, die vorhanden sein müssen, damit die Anfrage als vertrauenswürdig gilt
gateway.auth.trustedProxy.allowUsersNeinAllowlist von Benutzeridentitäten. Leer bedeutet: alle authentifizierten Benutzer erlauben.

TLS-Terminierung und HSTS

Verwende einen TLS-Terminierungspunkt und wende HSTS dort an.

Empfohlenes Muster: Proxy-TLS-Terminierung

Wenn dein Reverse-Proxy HTTPS für https://control.example.com handhabt, setze Strict-Transport-Security am Proxy für diese Domain.

  • Gute Wahl für internetexponierte Deployments.
  • Hält Zertifikat + HTTP-Härtungs-Policy an einem Ort.
  • OpenClaw kann hinter dem Proxy auf Loopback-HTTP bleiben.

Beispiel-Header-Wert:

Strict-Transport-Security: max-age=31536000; includeSubDomains

Gateway-TLS-Terminierung

Wenn OpenClaw selbst direkt HTTPS bereitstellt (kein TLS-terminierender Proxy), setze:

{
  gateway: {
    tls: { enabled: true },
    http: {
      securityHeaders: {
        strictTransportSecurity: "max-age=31536000; includeSubDomains",
      },
    },
  },
}

strictTransportSecurity akzeptiert einen String-Header-Wert oder false zum expliziten Deaktivieren.

Rollout-Empfehlungen

  • Beginne mit einer kurzen Max-Age (z. B. max-age=300) während der Validierung des Traffics.
  • Erhöhe auf langlebige Werte (z. B. max-age=31536000) erst nach ausreichend Vertrauen.
  • Füge includeSubDomains nur hinzu, wenn jede Subdomain HTTPS-bereit ist.
  • Verwende Preload nur, wenn du bewusst die Preload-Anforderungen für dein gesamtes Domain-Set erfüllst.
  • Loopback-only lokale Entwicklung profitiert nicht von HSTS.

Proxy-Setup-Beispiele

Pomerium

Pomerium übergibt die Identität in x-pomerium-claim-email (oder anderen Claim-Headern) und ein JWT in x-pomerium-jwt-assertion.

{
  gateway: {
    bind: "lan",
    trustedProxies: ["10.0.0.1"], // Pomeriums IP
    auth: {
      mode: "trusted-proxy",
      trustedProxy: {
        userHeader: "x-pomerium-claim-email",
        requiredHeaders: ["x-pomerium-jwt-assertion"],
      },
    },
  },
}

Pomerium-Konfigurationsauszug:

routes:
  - from: https://openclaw.example.com
    to: http://openclaw-gateway:18789
    policy:
      - allow:
          or:
            - email:
                is: [email protected]
    pass_identity_headers: true

Caddy mit OAuth

Caddy mit dem caddy-security-Plugin kann Benutzer authentifizieren und Identity-Header weiterleiten.

{
  gateway: {
    bind: "lan",
    trustedProxies: ["127.0.0.1"], // Caddys IP (wenn auf demselben Host)
    auth: {
      mode: "trusted-proxy",
      trustedProxy: {
        userHeader: "x-forwarded-user",
      },
    },
  },
}

Caddyfile-Auszug:

openclaw.example.com {
    authenticate with oauth2_provider
    authorize with policy1

    reverse_proxy openclaw:18789 {
        header_up X-Forwarded-User {http.auth.user.email}
    }
}

nginx + oauth2-proxy

oauth2-proxy authentifiziert Benutzer und übergibt die Identität in x-auth-request-email.

{
  gateway: {
    bind: "lan",
    trustedProxies: ["10.0.0.1"], // nginx/oauth2-proxy IP
    auth: {
      mode: "trusted-proxy",
      trustedProxy: {
        userHeader: "x-auth-request-email",
      },
    },
  },
}

nginx-Konfigurationsauszug:

location / {
    auth_request /oauth2/auth;
    auth_request_set $user $upstream_http_x_auth_request_email;

    proxy_pass http://openclaw:18789;
    proxy_set_header X-Auth-Request-Email $user;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
}

Traefik mit Forward-Auth

{
  gateway: {
    bind: "lan",
    trustedProxies: ["172.17.0.1"], // Traefik-Container-IP
    auth: {
      mode: "trusted-proxy",
      trustedProxy: {
        userHeader: "x-forwarded-user",
      },
    },
  },
}

Sicherheits-Checkliste

Überprüfe vor der Aktivierung von Trusted-Proxy-Auth:

  • Proxy ist der einzige Weg: Der Gateway-Port ist per Firewall gegen alles außer deinem Proxy geschützt
  • trustedProxies ist minimal: Nur die tatsächlichen Proxy-IPs, keine ganzen Subnetze
  • Proxy entfernt Header: Dein Proxy überschreibt (nicht anhängt) x-forwarded-*-Header von Clients
  • TLS-Terminierung: Dein Proxy handhabt TLS; Benutzer verbinden sich via HTTPS
  • allowUsers ist gesetzt (empfohlen): Auf bekannte Benutzer einschränken statt jeden Authentifizierten zuzulassen

Security Audit

openclaw security audit markiert Trusted-Proxy-Auth mit einem Finding der Schwere critical. Das ist beabsichtigt — es erinnert daran, dass du die Sicherheit an dein Proxy-Setup delegierst.

Das Audit prüft auf:

  • Fehlende trustedProxies-Konfiguration
  • Fehlende userHeader-Konfiguration
  • Leere allowUsers (erlaubt jeden authentifizierten Benutzer)

Fehlerbehebung

”trusted_proxy_untrusted_source”

Die Anfrage kam nicht von einer IP in gateway.trustedProxies. Prüfe:

  • Stimmt die Proxy-IP? (Docker-Container-IPs können sich ändern)
  • Gibt es einen Load-Balancer vor deinem Proxy?
  • Verwende docker inspect oder kubectl get pods -o wide, um die tatsächlichen IPs zu finden

”trusted_proxy_user_missing”

Der User-Header war leer oder fehlte. Prüfe:

  • Ist dein Proxy konfiguriert, Identity-Header weiterzuleiten?
  • Stimmt der Header-Name? (Case-insensitive, aber Schreibweise zählt)
  • Ist der Benutzer tatsächlich beim Proxy authentifiziert?

“trustedproxy_missing_header*”

Ein erforderlicher Header war nicht vorhanden. Prüfe:

  • Die Proxy-Konfiguration für diese spezifischen Header
  • Ob Header irgendwo in der Kette entfernt werden

”trusted_proxy_user_not_allowed”

Der Benutzer ist authentifiziert, aber nicht in allowUsers. Entweder hinzufügen oder die Allowlist entfernen.

WebSocket schlägt weiterhin fehl

Stelle sicher, dass dein Proxy:

  • WebSocket-Upgrades unterstützt (Upgrade: websocket, Connection: upgrade)
  • Die Identity-Header bei WebSocket-Upgrade-Requests weiterleitet (nicht nur bei HTTP)
  • Keinen separaten Auth-Pfad für WebSocket-Verbindungen hat

Migration von Token-Auth

Wenn du von Token-Auth zu Trusted-Proxy wechselst:

  1. Konfiguriere deinen Proxy zur Benutzer-Authentifizierung und Header-Weiterleitung
  2. Teste das Proxy-Setup unabhängig (curl mit Headern)
  3. Aktualisiere die OpenClaw-Konfiguration mit Trusted-Proxy-Auth
  4. Starte das Gateway neu
  5. Teste WebSocket-Verbindungen von der Control-UI
  6. Führe openclaw security audit aus und prüfe die Befunde

Verwandt