Gateway
Autenticação de proxy confiável
Quando usar
Use o modo de autenticação trusted-proxy quando:
- Você executa o OpenClaw atrás de um proxy com reconhecimento de identidade (Pomerium, Caddy + OAuth, nginx + oauth2-proxy, Traefik + forward auth).
- Seu proxy gerencia toda a autenticação e passa a identidade do usuário por cabeçalhos.
- Você está em um ambiente Kubernetes ou de contêiner em que o proxy é o único caminho para o Gateway.
- Você está encontrando erros WebSocket
1008 unauthorizedporque os navegadores não conseguem passar tokens em payloads WS.
Quando NÃO usar
- Se seu proxy não autentica usuários (apenas um terminador TLS ou balanceador de carga).
- Se houver qualquer caminho para o Gateway que contorne o proxy (brechas no firewall, acesso pela rede interna).
- Se você não tiver certeza de que seu proxy remove/substitui corretamente os cabeçalhos encaminhados.
- Se você só precisa de acesso pessoal para um único usuário (considere Tailscale Serve + loopback para uma configuração mais simples).
Como funciona
O proxy autentica o usuário
Seu proxy reverso autentica usuários (OAuth, OIDC, SAML etc.).
O proxy adiciona um cabeçalho de identidade
O proxy adiciona um cabeçalho com a identidade do usuário autenticado (por exemplo, x-forwarded-user: nick@example.com).
O Gateway verifica a origem confiável
O OpenClaw verifica se a solicitação veio de um IP de proxy confiável (configurado em gateway.trustedProxies).
O Gateway extrai a identidade
O OpenClaw extrai a identidade do usuário do cabeçalho configurado.
Autorizar
Se tudo estiver correto, a solicitação é autorizada.
Comportamento de pareamento da Control UI
Quando gateway.auth.mode = "trusted-proxy" está ativo e a solicitação passa nas verificações de trusted-proxy, as sessões WebSocket da Control UI podem se conectar sem identidade de pareamento de dispositivo.
Implicações de escopo:
- Sessões WebSocket da Control UI sem dispositivo se conectam, mas não recebem escopos de operador por padrão. O OpenClaw limpa a lista de escopos solicitados para
[]para que uma sessão que não esteja vinculada a um dispositivo/token pareado aprovado não possa declarar permissões por conta própria. - Se métodos falharem com
missing scopeapós uma conexão WebSocket bem-sucedida, use HTTPS para que o navegador possa gerar identidade de dispositivo e concluir o pareamento. Consulte HTTP inseguro da Control UI. - Apenas para emergência:
gateway.controlUi.dangerouslyDisableDeviceAuth=truepreserva os escopos solicitados mesmo sem identidade de dispositivo. Isso é um rebaixamento grave de segurança; reverta rapidamente. Consulte HTTP inseguro da Control UI.
Limitação de escopo por proxy reverso:
- Se seu proxy enviar
x-openclaw-scopesna solicitação de upgrade WebSocket da Control UI, o OpenClaw limita os escopos da sessão à interseção entre os escopos solicitados e os escopos declarados. Esse cabeçalho não concede escopos; ele apenas restringe o que a sessão pode manter.
Implicações:
- O pareamento deixa de ser o gate principal para acesso à Control UI neste modo.
- A política de autenticação do seu proxy reverso e
allowUserspassam a ser o controle de acesso efetivo. - Mantenha a entrada do gateway bloqueada apenas para IPs de proxy confiáveis (
gateway.trustedProxies+ firewall).
Clientes WebSocket personalizados não são sessões da Control UI. gateway.controlUi.dangerouslyDisableDeviceAuth não concede escopos a clientes arbitrários client.mode: "backend" ou com formato de CLI. Automações personalizadas devem usar identidade/pareamento de dispositivo, o caminho auxiliar backend direto-local reservado client.id: "gateway-client" ou o Plugin HTTP RPC de administração quando uma superfície HTTP de solicitação/resposta for mais adequada.
Configuração
{ 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, }, }, },}Referência de configuração
gateway.trustedProxiesstring[]requiredArray de endereços IP de proxy nos quais confiar. Solicitações de outros IPs são rejeitadas.
gateway.auth.modestringrequiredDeve ser "trusted-proxy".
gateway.auth.trustedProxy.userHeaderstringrequiredNome do cabeçalho que contém a identidade do usuário autenticado.
gateway.auth.trustedProxy.requiredHeadersstring[]Cabeçalhos adicionais que devem estar presentes para que a solicitação seja confiável.
gateway.auth.trustedProxy.allowUsersstring[]Lista de permissão de identidades de usuário. Vazio significa permitir todos os usuários autenticados.
gateway.auth.trustedProxy.allowLoopbackbooleanSuporte opt-in para proxies reversos loopback no mesmo host. O padrão é false.
Terminação TLS e HSTS
Use um único ponto de terminação TLS e aplique HSTS nele.
Terminação TLS no proxy (recomendado)
Quando seu proxy reverso gerencia HTTPS para https://control.example.com, defina Strict-Transport-Security no proxy para esse domínio.
- Boa opção para implantações expostas à internet.
- Mantém a política de certificado + proteção HTTP em um só lugar.
- O OpenClaw pode permanecer em HTTP loopback atrás do proxy.
Valor de cabeçalho de exemplo:
Strict-Transport-Security: max-age=31536000; includeSubDomainsTerminação TLS no Gateway
Se o próprio OpenClaw servir HTTPS diretamente (sem proxy com terminação TLS), defina:
{ gateway: { tls: { enabled: true }, http: { securityHeaders: { strictTransportSecurity: "max-age=31536000; includeSubDomains", }, }, },}strictTransportSecurity aceita um valor de cabeçalho em string ou false para desabilitar explicitamente.
Orientação de implantação
- Comece primeiro com uma idade máxima curta (por exemplo,
max-age=300) enquanto valida o tráfego. - Aumente para valores de longa duração (por exemplo,
max-age=31536000) somente depois que a confiança estiver alta. - Adicione
includeSubDomainsapenas se todos os subdomínios estiverem prontos para HTTPS. - Use preload apenas se você atender intencionalmente aos requisitos de preload para todo o seu conjunto de domínios.
- O desenvolvimento local apenas em loopback não se beneficia de HSTS.
Exemplos de configuração de proxy
Pomerium
O Pomerium passa identidade em x-pomerium-claim-email (ou outros cabeçalhos de declaração) e um JWT em 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"], }, }, },}Trecho de configuração do Pomerium:
routes: - from: https://openclaw.example.com to: http://openclaw-gateway:18789 policy: - allow: or: - email: is: nick@example.com pass_identity_headers: trueCaddy com OAuth
O Caddy com o Plugin caddy-security pode autenticar usuários e passar cabeçalhos de identidade.
{ gateway: { bind: "lan", trustedProxies: ["10.0.0.1"], // Caddy/sidecar proxy IP auth: { mode: "trusted-proxy", trustedProxy: { userHeader: "x-forwarded-user", }, }, },}Trecho de 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
O oauth2-proxy autentica usuários e passa identidade em 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", }, }, },}Trecho de configuração do 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 com forward auth
{ gateway: { bind: "lan", trustedProxies: ["172.17.0.1"], // Traefik container IP auth: { mode: "trusted-proxy", trustedProxy: { userHeader: "x-forwarded-user", }, }, },}Configuração mista de token
O OpenClaw rejeita configurações ambíguas em que tanto um gateway.auth.token (ou OPENCLAW_GATEWAY_TOKEN) quanto o modo trusted-proxy estão ativos ao mesmo tempo. Configurações mistas de token podem fazer com que solicitações loopback sejam autenticadas silenciosamente pelo caminho de autenticação errado.
Se você vir um erro mixed_trusted_proxy_token na inicialização:
- Remova o token compartilhado ao usar o modo trusted-proxy, ou
- Altere
gateway.auth.modepara"token"se você pretende usar autenticação baseada em token.
A identidade por cabeçalhos de proxy confiável em loopback ainda falha fechada: chamadores no mesmo host não são autenticados silenciosamente como usuários do proxy. Chamadores internos do OpenClaw que contornam o proxy podem se autenticar com gateway.auth.password / OPENCLAW_GATEWAY_PASSWORD em vez disso. O fallback por token continua intencionalmente sem suporte no modo de proxy confiável.
Cabeçalho de escopos do operador
A autenticação por proxy confiável é um modo HTTP portador de identidade, portanto os chamadores podem declarar opcionalmente escopos de operador com x-openclaw-scopes em requisições da API HTTP.
Observação: os escopos de WebSocket são determinados pelo handshake do protocolo Gateway e pela vinculação de identidade do dispositivo. Em requisições de upgrade WebSocket da Control UI, x-openclaw-scopes é apenas um limite para os escopos negociados da sessão, não uma concessão. Para o comportamento de escopos WebSocket com proxy confiável, consulte comportamento de pareamento da Control UI.
Exemplos:
x-openclaw-scopes: operator.readx-openclaw-scopes: operator.read,operator.writex-openclaw-scopes: operator.admin,operator.write
Comportamento:
- Quando o cabeçalho está presente, o OpenClaw respeita o conjunto de escopos declarado.
- Quando o cabeçalho está presente, mas vazio, a requisição declara nenhum escopo de operador.
- Quando o cabeçalho está ausente, APIs HTTP normais portadoras de identidade recorrem ao conjunto padrão de escopos padrão do operador.
- Rotas HTTP de Plugin com autenticação pelo Gateway são mais restritas por padrão: quando
x-openclaw-scopesestá ausente, seu escopo de runtime recai paraoperator.write. - Requisições HTTP originadas no navegador ainda precisam passar por
gateway.controlUi.allowedOrigins(ou pelo modo deliberado de fallback de cabeçalho Host), mesmo depois que a autenticação por proxy confiável é bem-sucedida. - Para sessões WebSocket da Control UI,
x-openclaw-scopesé um limite de escopo quando presente na requisição de upgrade. Um valor vazio resulta em nenhum escopo.
Regra prática: envie x-openclaw-scopes explicitamente quando quiser que uma requisição por proxy confiável seja mais restrita que os padrões, ou quando uma rota de Plugin com autenticação pelo Gateway precisar de algo mais forte que escopo de escrita.
Checklist de segurança
Antes de habilitar a autenticação por proxy confiável, verifique:
- [ ] Proxy é o único caminho: A porta do Gateway está protegida por firewall contra tudo, exceto seu proxy.
- [ ] trustedProxies é mínimo: Apenas os IPs reais do seu proxy, não sub-redes inteiras.
- [ ] Fonte de proxy por loopback é deliberada: a autenticação por proxy confiável falha fechada para requisições com origem em loopback, a menos que
gateway.auth.trustedProxy.allowLoopbackesteja explicitamente habilitado para um proxy no mesmo host. - [ ] Proxy remove cabeçalhos: Seu proxy sobrescreve (não acrescenta) cabeçalhos
x-forwarded-*dos clientes. - [ ] Terminação TLS: Seu proxy lida com TLS; usuários se conectam via HTTPS.
- [ ] allowedOrigins é explícito: Control UI sem loopback usa
gateway.controlUi.allowedOriginsexplícito. - [ ] allowUsers está definido (recomendado): Restrinja a usuários conhecidos em vez de permitir qualquer pessoa autenticada.
- [ ] Sem configuração mista de token: Não defina
gateway.auth.tokenegateway.auth.mode: "trusted-proxy"ao mesmo tempo. - [ ] Fallback de senha local é privado: Se você configurar
gateway.auth.passwordpara chamadores internos diretos, mantenha a porta do Gateway protegida por firewall para que clientes remotos fora do proxy não possam alcançá-la diretamente.
Auditoria de segurança
openclaw security audit sinalizará autenticação por proxy confiável com um achado de severidade crítica. Isso é intencional: é um lembrete de que você está delegando a segurança à configuração do seu proxy.
A auditoria verifica:
- Lembrete/aviso crítico base
gateway.trusted_proxy_auth - Configuração
trustedProxiesausente - Configuração
userHeaderausente allowUsersvazio (permite qualquer usuário autenticado)allowLoopbackhabilitado para origens de proxy no mesmo host- Política de origem de navegador curinga ou ausente em superfícies expostas da Control UI
Solução de problemas
trusted_proxy_untrusted_source
A requisição não veio de um IP em gateway.trustedProxies. Verifique:
- O IP do proxy está correto? (IPs de contêineres Docker podem mudar.)
- Há um balanceador de carga na frente do seu proxy?
- Use
docker inspectoukubectl get pods -o widepara encontrar os IPs reais.
trusted_proxy_loopback_source
O OpenClaw rejeitou uma requisição de proxy confiável com origem em loopback.
Verifique:
- O proxy está se conectando a partir de
127.0.0.1/::1? - Você está tentando usar autenticação por proxy confiável com um proxy reverso de loopback no mesmo host?
Correção:
- Prefira autenticação por token/senha para clientes internos no mesmo host que não passam pelo proxy, ou
- Roteie por um endereço de proxy confiável que não seja loopback e mantenha esse IP em
gateway.trustedProxies, ou - Para um proxy reverso deliberado no mesmo host, defina
gateway.auth.trustedProxy.allowLoopback = true, mantenha o endereço de loopback emgateway.trustedProxiese garanta que o proxy remova ou sobrescreva cabeçalhos de identidade.
trusted_proxy_user_missing
O cabeçalho de usuário estava vazio ou ausente. Verifique:
- Seu proxy está configurado para passar cabeçalhos de identidade?
- O nome do cabeçalho está correto? (não diferencia maiúsculas de minúsculas, mas a grafia importa)
- O usuário está realmente autenticado no proxy?
trusted_proxy_missing_header_*
Um cabeçalho obrigatório não estava presente. Verifique:
- A configuração do seu proxy para esses cabeçalhos específicos.
- Se os cabeçalhos estão sendo removidos em algum ponto da cadeia.
trusted_proxy_user_not_allowed
O usuário está autenticado, mas não está em allowUsers. Adicione-o ou remova a lista de permissões.
trusted_proxy_origin_not_allowed
A autenticação por proxy confiável foi bem-sucedida, mas o cabeçalho Origin do navegador não passou nas verificações de origem da Control UI.
Verifique:
gateway.controlUi.allowedOriginsinclui a origem exata do navegador.- Você não está dependendo de origens curinga, a menos que queira intencionalmente um comportamento de permitir tudo.
- Se você usa intencionalmente o modo de fallback de cabeçalho Host,
gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback=trueestá definido deliberadamente.
A conexão é bem-sucedida, mas os métodos relatam escopo ausente
O WebSocket conecta, mas chat.history, sessions.list ou
models.list falha com missing scope: operator.read.
Causas comuns:
- Sessão da Control UI sem dispositivo: a autenticação por proxy confiável pode admitir a conexão WebSocket sem identidade de dispositivo, mas o OpenClaw limpa os escopos em sessões sem dispositivo por design.
- Cliente de backend personalizado:
gateway.controlUi.dangerouslyDisableDeviceAuthtem escopo da Control UI e não concede escopos a clientes WebSocket arbitrários em formato de backend ou CLI. x-openclaw-scopesexcessivamente restrito: se seu proxy injeta esse cabeçalho na requisição de upgrade WebSocket da Control UI, os escopos da sessão são limitados a esse conjunto. Um valor de cabeçalho vazio resulta em nenhum escopo.
Correção:
- Para a Control UI, use HTTPS para que o navegador possa gerar identidade de dispositivo e concluir o pareamento.
- Para automação personalizada, use identidade de dispositivo/pareamento, o caminho auxiliar de backend reservado
gateway-clientdireto-local ou RPC HTTP de administração. - Use
gateway.controlUi.dangerouslyDisableDeviceAuth: trueapenas como um caminho temporário de emergência para a Control UI.
WebSocket ainda falhando
Garanta que seu proxy:
- Suporte upgrades de WebSocket (
Upgrade: websocket,Connection: upgrade). - Passe os cabeçalhos de identidade em requisições de upgrade WebSocket (não apenas HTTP).
- Não tenha um caminho de autenticação separado para conexões WebSocket.
Migração da autenticação por token
Se você está migrando da autenticação por token para proxy confiável:
Configure o proxy
Configure seu proxy para autenticar usuários e passar cabeçalhos.
Teste o proxy independentemente
Teste a configuração do proxy independentemente (curl com cabeçalhos).
Atualize a configuração do OpenClaw
Atualize a configuração do OpenClaw com autenticação por proxy confiável.
Reinicie o Gateway
Reinicie o Gateway.
Teste WebSocket
Teste conexões WebSocket a partir da Control UI.
Auditoria
Execute openclaw security audit e revise os achados.
Relacionados
- Configuração — referência de configuração
- Acesso remoto — outros padrões de acesso remoto
- Segurança — guia de segurança completo
- Tailscale — alternativa mais simples para acesso somente por tailnet