Gateway
Autenticazione proxy attendibile
Quando usarla
Usa la modalità di autenticazione trusted-proxy quando:
- Esegui OpenClaw dietro un proxy consapevole dell'identità (Pomerium, Caddy + OAuth, nginx + oauth2-proxy, Traefik + forward auth).
- Il tuo proxy gestisce tutta l'autenticazione e passa l'identità utente tramite header.
- Sei in un ambiente Kubernetes o container in cui il proxy è l'unico percorso verso il Gateway.
- Riscontri errori WebSocket
1008 unauthorizedperché i browser non possono passare token nei payload WS.
Quando NON usarla
- Se il tuo proxy non autentica gli utenti (solo un terminatore TLS o un load balancer).
- Se esiste un percorso verso il Gateway che aggira il proxy (buchi nel firewall, accesso alla rete interna).
- Se non sei sicuro che il tuo proxy rimuova/sovrascriva correttamente gli header inoltrati.
- Se ti serve solo accesso personale per un singolo utente (considera Tailscale Serve + loopback per una configurazione più semplice).
Come funziona
Proxy authenticates the user
Il tuo reverse proxy autentica gli utenti (OAuth, OIDC, SAML, ecc.).
Proxy adds an identity header
Il proxy aggiunge un header con l'identità dell'utente autenticato (ad esempio, x-forwarded-user: nick@example.com).
Gateway verifies trusted source
OpenClaw verifica che la richiesta provenga da un IP proxy attendibile (configurato in gateway.trustedProxies).
Gateway extracts identity
OpenClaw estrae l'identità utente dall'header configurato.
Authorize
Se tutti i controlli vanno a buon fine, la richiesta viene autorizzata.
Comportamento di associazione della Control UI
Quando gateway.auth.mode = "trusted-proxy" è attivo e la richiesta supera i controlli trusted-proxy, le sessioni WebSocket della Control UI possono connettersi senza identità di associazione del dispositivo.
Implicazioni dell'ambito:
- Le sessioni WebSocket della Control UI senza dispositivo si connettono ma, per impostazione predefinita, non ricevono ambiti operatore. OpenClaw azzera l'elenco degli ambiti richiesti a
[], così una sessione non vincolata a un dispositivo/token associato e approvato non può autodichiarare autorizzazioni. - Se i metodi non riescono con
missing scopedopo una connessione WebSocket riuscita, usa HTTPS così il browser può generare l'identità del dispositivo e completare l'associazione. Vedi HTTP non sicuro della Control UI. - Solo per emergenza:
gateway.controlUi.dangerouslyDisableDeviceAuth=trueconserva gli ambiti richiesti anche senza identità del dispositivo. Questo è un grave downgrade di sicurezza; ripristinalo rapidamente. Vedi HTTP non sicuro della Control UI.
Limitazione degli ambiti tramite reverse proxy:
- Se il tuo proxy invia
x-openclaw-scopesnella richiesta di upgrade WebSocket della Control UI, OpenClaw limita gli ambiti della sessione all'intersezione tra gli ambiti richiesti e quelli dichiarati. Questo header non concede ambiti; restringe soltanto ciò che la sessione può detenere.
Implicazioni:
- In questa modalità, l'associazione non è più il gate principale per l'accesso alla Control UI.
- La policy di autenticazione del tuo reverse proxy e
allowUsersdiventano il controllo di accesso effettivo. - Mantieni l'ingresso del Gateway bloccato solo agli IP proxy attendibili (
gateway.trustedProxies+ firewall).
I client WebSocket personalizzati non sono sessioni della Control UI. gateway.controlUi.dangerouslyDisableDeviceAuth non concede ambiti a client arbitrari client.mode: "backend" o con forma CLI. Le automazioni personalizzate devono usare identità/associazione del dispositivo, il percorso helper backend direct-local riservato client.id: "gateway-client", oppure il Plugin admin HTTP RPC quando una superficie richiesta/risposta HTTP è più adatta.
Configurazione
{ gateway: { // Trusted-proxy auth expects requests from a non-loopback trusted proxy source by default bind: "lan", // CRITICAL: Only add your proxy's IP(s) here trustedProxies: ["10.0.0.1", "172.17.0.1"], auth: { mode: "trusted-proxy", trustedProxy: { // Header containing authenticated user identity (required) userHeader: "x-forwarded-user", // Optional: headers that MUST be present (proxy verification) requiredHeaders: ["x-forwarded-proto", "x-forwarded-host"], // Optional: restrict to specific users (empty = allow all) allowUsers: ["nick@example.com", "admin@company.org"], // Optional: allow a same-host loopback proxy after explicit opt-in allowLoopback: false, }, }, },}Riferimento di configurazione
gateway.trustedProxiesstring[]requiredArray di indirizzi IP proxy da considerare attendibili. Le richieste da altri IP vengono rifiutate.
gateway.auth.modestringrequiredDeve essere "trusted-proxy".
gateway.auth.trustedProxy.userHeaderstringrequiredNome dell'header che contiene l'identità dell'utente autenticato.
gateway.auth.trustedProxy.requiredHeadersstring[]Header aggiuntivi che devono essere presenti affinché la richiesta sia considerata attendibile.
gateway.auth.trustedProxy.allowUsersstring[]Allowlist delle identità utente. Vuoto significa consentire tutti gli utenti autenticati.
gateway.auth.trustedProxy.allowLoopbackbooleanSupporto opt-in per reverse proxy loopback sullo stesso host. Il valore predefinito è false.
Terminazione TLS e HSTS
Usa un unico punto di terminazione TLS e applica HSTS lì.
Proxy TLS termination (recommended)
Quando il tuo reverse proxy gestisce HTTPS per https://control.example.com, imposta Strict-Transport-Security sul proxy per quel dominio.
- Adatto per distribuzioni esposte a internet.
- Mantiene la policy di certificati e hardening HTTP in un solo punto.
- OpenClaw può restare su HTTP loopback dietro il proxy.
Valore di header di esempio:
Strict-Transport-Security: max-age=31536000; includeSubDomainsGateway TLS termination
Se OpenClaw serve direttamente HTTPS (senza un proxy che termina TLS), imposta:
{ gateway: { tls: { enabled: true }, http: { securityHeaders: { strictTransportSecurity: "max-age=31536000; includeSubDomains", }, }, },}strictTransportSecurity accetta un valore header stringa oppure false per disabilitarlo esplicitamente.
Indicazioni di rollout
- Inizia prima con una durata massima breve (ad esempio
max-age=300) durante la convalida del traffico. - Aumenta a valori di lunga durata (ad esempio
max-age=31536000) solo dopo aver raggiunto un'elevata fiducia. - Aggiungi
includeSubDomainssolo se ogni sottodominio è pronto per HTTPS. - Usa preload solo se soddisfi intenzionalmente i requisiti di preload per l'intero insieme di domini.
- Lo sviluppo locale solo loopback non beneficia di HSTS.
Esempi di configurazione del proxy
Pomerium
Pomerium passa l'identità in x-pomerium-claim-email (o altri header claim) e un JWT in x-pomerium-jwt-assertion.
{ gateway: { bind: "lan", trustedProxies: ["10.0.0.1"], // Pomerium's IP auth: { mode: "trusted-proxy", trustedProxy: { userHeader: "x-pomerium-claim-email", requiredHeaders: ["x-pomerium-jwt-assertion"], }, }, },}Frammento di configurazione Pomerium:
routes: - from: https://openclaw.example.com to: http://openclaw-gateway:18789 policy: - allow: or: - email: is: nick@example.com pass_identity_headers: trueCaddy with OAuth
Caddy con il Plugin caddy-security può autenticare gli utenti e passare header di identità.
{ gateway: { bind: "lan", trustedProxies: ["10.0.0.1"], // Caddy/sidecar proxy IP auth: { mode: "trusted-proxy", trustedProxy: { userHeader: "x-forwarded-user", }, }, },}Frammento di Caddyfile:
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 autentica gli utenti e passa l'identità 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", }, }, },}Frammento di configurazione nginx:
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 with forward auth
{ gateway: { bind: "lan", trustedProxies: ["172.17.0.1"], // Traefik container IP auth: { mode: "trusted-proxy", trustedProxy: { userHeader: "x-forwarded-user", }, }, },}Configurazione mista dei token
OpenClaw rifiuta configurazioni ambigue in cui sia un gateway.auth.token (o OPENCLAW_GATEWAY_TOKEN) sia la modalità trusted-proxy sono attivi contemporaneamente. Le configurazioni miste dei token possono far sì che le richieste loopback vengano autenticate silenziosamente sul percorso di autenticazione sbagliato.
Se visualizzi un errore mixed_trusted_proxy_token all'avvio:
- Rimuovi il token condiviso quando usi la modalità trusted-proxy, oppure
- Passa
gateway.auth.modea"token"se intendi usare autenticazione basata su token.
Le intestazioni di identità trusted-proxy di loopback continuano a fallire in modo chiuso: i chiamanti sullo stesso host non vengono autenticati silenziosamente come utenti del proxy. I chiamanti interni di OpenClaw che aggirano il proxy possono invece autenticarsi con gateway.auth.password / OPENCLAW_GATEWAY_PASSWORD. Il fallback tramite token rimane intenzionalmente non supportato in modalità trusted-proxy.
Intestazione degli ambiti operatore
L'autenticazione trusted-proxy è una modalità HTTP portatrice di identità, quindi i chiamanti possono facoltativamente dichiarare gli ambiti operatore con x-openclaw-scopes nelle richieste API HTTP.
Nota: gli ambiti WebSocket sono determinati dall'handshake del protocollo Gateway e dal binding dell'identità del dispositivo. Nelle richieste di upgrade WebSocket della Control UI, x-openclaw-scopes è solo un limite massimo sugli ambiti di sessione negoziati, non una concessione. Per il comportamento degli ambiti WebSocket con trusted-proxy, consulta comportamento di associazione della Control UI.
Esempi:
x-openclaw-scopes: operator.readx-openclaw-scopes: operator.read,operator.writex-openclaw-scopes: operator.admin,operator.write
Comportamento:
- Quando l'intestazione è presente, OpenClaw rispetta l'insieme di ambiti dichiarato.
- Quando l'intestazione è presente ma vuota, la richiesta dichiara nessun ambito operatore.
- Quando l'intestazione è assente, le normali API HTTP portatrici di identità ricadono sull'insieme standard di ambiti operatore predefiniti.
- Le route HTTP dei Plugin con autenticazione Gateway sono più ristrette per impostazione predefinita: quando
x-openclaw-scopesè assente, il loro ambito runtime ricade suoperator.write. - Le richieste HTTP di origine browser devono comunque superare
gateway.controlUi.allowedOrigins(o la modalità deliberata di fallback dell'intestazione Host) anche dopo il successo dell'autenticazione trusted-proxy. - Per le sessioni WebSocket della Control UI,
x-openclaw-scopesè un limite massimo degli ambiti quando è presente nella richiesta di upgrade. Un valore vuoto non produce alcun ambito.
Regola pratica: invia x-openclaw-scopes esplicitamente quando vuoi che una richiesta trusted-proxy sia più ristretta dei valori predefiniti, oppure quando una route di Plugin con autenticazione Gateway richiede qualcosa di più forte dell'ambito di scrittura.
Checklist di sicurezza
Prima di abilitare l'autenticazione trusted-proxy, verifica:
- [ ] Il proxy è l'unico percorso: la porta del Gateway è protetta da firewall da tutto tranne che dal tuo proxy.
- [ ] trustedProxies è minimale: solo gli IP reali del tuo proxy, non intere sottoreti.
- [ ] La sorgente proxy loopback è deliberata: l'autenticazione trusted-proxy fallisce in modo chiuso per le richieste con sorgente loopback, a meno che
gateway.auth.trustedProxy.allowLoopbacknon sia abilitato esplicitamente per un proxy sullo stesso host. - [ ] Il proxy rimuove le intestazioni: il tuo proxy sovrascrive (non accoda) le intestazioni
x-forwarded-*provenienti dai client. - [ ] Terminazione TLS: il tuo proxy gestisce TLS; gli utenti si connettono tramite HTTPS.
- [ ] allowedOrigins è esplicito: la Control UI non loopback usa
gateway.controlUi.allowedOriginsespliciti. - [ ] allowUsers è impostato (consigliato): limita agli utenti noti invece di consentire chiunque sia autenticato.
- [ ] Nessuna configurazione token mista: non impostare contemporaneamente
gateway.auth.tokenegateway.auth.mode: "trusted-proxy". - [ ] Il fallback con password locale è privato: se configuri
gateway.auth.passwordper chiamanti diretti interni, mantieni la porta del Gateway protetta da firewall in modo che i client remoti non proxy non possano raggiungerla direttamente.
Audit di sicurezza
openclaw security audit segnalerà l'autenticazione trusted-proxy con una rilevanza critica. È intenzionale: è un promemoria del fatto che stai delegando la sicurezza alla configurazione del tuo proxy.
L'audit controlla:
- Avviso/promemoria critico di base
gateway.trusted_proxy_auth - Configurazione
trustedProxiesmancante - Configurazione
userHeadermancante allowUsersvuoto (consente qualsiasi utente autenticato)allowLoopbackabilitato per sorgenti proxy sullo stesso host- Criterio di origine browser con wildcard o mancante sulle superfici esposte della Control UI
Risoluzione dei problemi
trusted_proxy_untrusted_source
La richiesta non proveniva da un IP in gateway.trustedProxies. Controlla:
- L'IP del proxy è corretto? (Gli IP dei container Docker possono cambiare.)
- C'è un load balancer davanti al tuo proxy?
- Usa
docker inspectokubectl get pods -o wideper trovare gli IP effettivi.
trusted_proxy_loopback_source
OpenClaw ha rifiutato una richiesta trusted-proxy con sorgente loopback.
Controlla:
- Il proxy si connette da
127.0.0.1/::1? - Stai tentando di usare l'autenticazione trusted-proxy con un reverse proxy loopback sullo stesso host?
Correzione:
- Preferisci l'autenticazione token/password per i client interni sullo stesso host che non passano attraverso il proxy, oppure
- instrada attraverso un indirizzo proxy attendibile non loopback e mantieni quell'IP in
gateway.trustedProxies, oppure - per un reverse proxy deliberato sullo stesso host, imposta
gateway.auth.trustedProxy.allowLoopback = true, mantieni l'indirizzo loopback ingateway.trustedProxiese assicurati che il proxy rimuova o sovrascriva le intestazioni di identità.
trusted_proxy_user_missing
L'intestazione utente era vuota o mancante. Controlla:
- Il tuo proxy è configurato per passare le intestazioni di identità?
- Il nome dell'intestazione è corretto? (non fa distinzione tra maiuscole e minuscole, ma l'ortografia conta)
- L'utente è effettivamente autenticato presso il proxy?
trusted_proxy_missing_header_*
Un'intestazione obbligatoria non era presente. Controlla:
- La configurazione del tuo proxy per quelle intestazioni specifiche.
- Se le intestazioni vengono rimosse da qualche parte nella catena.
trusted_proxy_user_not_allowed
L'utente è autenticato ma non è in allowUsers. Aggiungilo oppure rimuovi l'allowlist.
trusted_proxy_origin_not_allowed
L'autenticazione trusted-proxy è riuscita, ma l'intestazione browser Origin non ha superato i controlli di origine della Control UI.
Controlla:
gateway.controlUi.allowedOriginsinclude l'origine browser esatta.- Non ti stai affidando a origini wildcard a meno che tu non voglia intenzionalmente un comportamento che consenta tutto.
- Se usi intenzionalmente la modalità di fallback dell'intestazione Host,
gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback=trueè impostato deliberatamente.
Connection succeeds but methods report missing scope
Il WebSocket si connette, ma chat.history, sessions.list o
models.list fallisce con missing scope: operator.read.
Cause comuni:
- Sessione Control UI senza dispositivo: l'autenticazione trusted-proxy può ammettere la connessione WebSocket senza identità del dispositivo, ma OpenClaw cancella gli ambiti sulle sessioni senza dispositivo per progettazione.
- Client backend personalizzato:
gateway.controlUi.dangerouslyDisableDeviceAuthè limitato alla Control UI e non concede ambiti a client WebSocket backend arbitrari o con forma da CLI. x-openclaw-scopestroppo ristretto: se il tuo proxy inietta questa intestazione nella richiesta di upgrade WebSocket della Control UI, gli ambiti di sessione sono limitati a quell'insieme. Un valore di intestazione vuoto non produce alcun ambito.
Correzione:
- Per la Control UI, usa HTTPS in modo che il browser possa generare l'identità del dispositivo e completare l'associazione.
- Per automazioni personalizzate, usa identità/associazione del dispositivo, il percorso helper backend diretto-locale riservato
gateway-clientoppure RPC HTTP admin. - Usa
gateway.controlUi.dangerouslyDisableDeviceAuth: truesolo come percorso temporaneo di emergenza per la Control UI.
WebSocket still failing
Assicurati che il tuo proxy:
- Supporti gli upgrade WebSocket (
Upgrade: websocket,Connection: upgrade). - Passi le intestazioni di identità nelle richieste di upgrade WebSocket (non solo HTTP).
- Non abbia un percorso di autenticazione separato per le connessioni WebSocket.
Migrazione dall'autenticazione token
Se stai passando dall'autenticazione token a trusted-proxy:
Configure the proxy
Configura il tuo proxy per autenticare gli utenti e passare le intestazioni.
Test the proxy independently
Testa la configurazione del proxy in modo indipendente (curl con intestazioni).
Update OpenClaw config
Aggiorna la configurazione di OpenClaw con l'autenticazione trusted-proxy.
Restart the Gateway
Riavvia il Gateway.
Test WebSocket
Testa le connessioni WebSocket dalla Control UI.
Audit
Esegui openclaw security audit e rivedi i risultati.
Correlati
- Configurazione — riferimento della configurazione
- Accesso remoto — altri pattern di accesso remoto
- Sicurezza — guida completa alla sicurezza
- Tailscale — alternativa più semplice per l'accesso solo tailnet