Gateway

Autenticação por proxy confiável

Quando usar

  • Você executa o OpenClaw por trás de um proxy com reconhecimento de identidade (Pomerium, Caddy + OAuth, nginx + oauth2-proxy, Traefik + autenticação encaminhada).
  • Seu proxy gerencia toda a autenticação e transmite a identidade do usuário por meio de cabeçalhos.
  • Você está em um ambiente Kubernetes ou de contêineres no qual o proxy é o único caminho até o Gateway.
  • Você está recebendo erros de WebSocket 1008 unauthorized porque os navegadores não conseguem transmitir tokens nas cargas úteis do WS.

Quando NÃO usar

  • Seu proxy não autentica usuários (é apenas um terminador TLS ou balanceador de carga).
  • Existe algum caminho até o Gateway que contorne o proxy (brechas no firewall, acesso pela rede interna).
  • Você não tem certeza se o proxy remove ou sobrescreve corretamente os cabeçalhos encaminhados.
  • Você precisa apenas de acesso pessoal para um único usuário (considere usar Tailscale Serve + local loopback).

Como funciona

  • O proxy autentica o usuário

    Seu proxy reverso autentica os 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 (gateway.trustedProxies) e se não é o endereço de local loopback ou de interface local do próprio Gateway.

  • O Gateway extrai a identidade

    O OpenClaw lê os cabeçalhos obrigatórios e, em seguida, a identidade do usuário no cabeçalho configurado.

  • Autorizar

    Se todas as verificações forem aprovadas e o usuário passar por allowUsers (quando definido), a solicitação será autorizada.

  • Configuração

    json5
    {  gateway: {    // Por padrão, a autenticação por proxy confiável espera que o IP de origem do proxy não seja de loopback    bind: "lan",     // CRÍTICO: adicione aqui somente os IPs do seu proxy    trustedProxies: ["10.0.0.1", "172.17.0.1"],     auth: {      mode: "trusted-proxy",      trustedProxy: {        // Cabeçalho que contém a identidade do usuário autenticado (obrigatório)        userHeader: "x-forwarded-user",         // Opcional: cabeçalhos que DEVEM estar presentes (verificação do proxy)        requiredHeaders: ["x-forwarded-proto", "x-forwarded-host"],         // Opcional: restringe a usuários específicos (vazio = permite todos)        allowUsers: ["nick@example.com", "admin@company.org"],         // Opcional: permite um proxy de loopback no mesmo host após adesão explícita        allowLoopback: false,      },    },  },}

    Referência de configuração

    gateway.trustedProxiesstring[]required

    Matriz de endereços IP (ou CIDRs) de proxies nos quais confiar. Solicitações provenientes de outros IPs são rejeitadas.

    gateway.auth.modestringrequired

    Deve ser "trusted-proxy".

    gateway.auth.trustedProxy.userHeaderstringrequired

    Nome 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 considerada confiável.

    gateway.auth.trustedProxy.allowUsersstring[]

    Lista de permissões de identidades de usuários. Vazia significa permitir todos os usuários autenticados.

    gateway.auth.trustedProxy.allowLoopbackbooleandefault: false

    Suporte opcional a proxies reversos de loopback no mesmo host.

    Comportamento de pareamento da UI de Controle

    Quando gateway.auth.mode = "trusted-proxy" está ativo e a solicitação passa pelas verificações de proxy confiável, as sessões WebSocket da UI de Controle podem se conectar sem uma identidade de pareamento de dispositivo.

    Implicações de escopo:

    • As sessões WebSocket da UI de Controle sem dispositivo se conectam, mas não recebem nenhum escopo de operador por padrão. O OpenClaw limpa a lista de escopos solicitados para [], impedindo que uma sessão não vinculada a um dispositivo/token pareado e aprovado declare permissões para si mesma.
    • Se métodos falharem com missing scope após uma conexão WebSocket bem-sucedida, use HTTPS para que o navegador possa gerar uma identidade de dispositivo e concluir o pareamento. Consulte HTTP não seguro da UI de Controle.
    • Somente em caso de emergência: gateway.controlUi.dangerouslyDisableDeviceAuth=true preserva os escopos solicitados mesmo sem identidade de dispositivo. Isso reduz gravemente a segurança; reverta rapidamente. Consulte HTTP não seguro da UI de Controle.

    Limitação de escopos pelo proxy reverso: se o proxy enviar x-openclaw-scopes na solicitação de upgrade do WebSocket da UI de Controle, o OpenClaw limitará os escopos da sessão à interseção entre os escopos solicitados e os declarados. Esse cabeçalho não concede escopos; ele apenas restringe os escopos que a sessão pode ter.

    Implicações:

    • O pareamento deixa de ser o controle principal para acesso à UI de Controle neste modo.
    • A política de autenticação do proxy reverso e allowUsers tornam-se o controle de acesso efetivo.
    • Mantenha a entrada do Gateway restrita somente aos IPs dos proxies confiáveis (gateway.trustedProxies + firewall).

    Clientes WebSocket personalizados não são sessões da UI de Controle. gateway.controlUi.dangerouslyDisableDeviceAuth não concede escopos a clientes arbitrários com client.mode: "backend" nem a clientes no formato da CLI. Automações personalizadas devem usar identidade de dispositivo/pareamento, o caminho auxiliar de backend reservado para acesso local direto com client.id: "gateway-client" ou o Plugin de RPC HTTP administrativo quando uma interface HTTP de solicitação/resposta for mais adequada.

    Cabeçalho de escopos do operador

    A autenticação por proxy confiável é um modo HTTP que carrega identidade; portanto, os chamadores podem, opcionalmente, declarar escopos de operador com x-openclaw-scopes nas solicitações à API HTTP.

    Observação: os escopos de WebSocket são determinados pelo handshake do protocolo do Gateway e pela vinculação da identidade do dispositivo. Nas solicitações de upgrade do WebSocket da UI de Controle, x-openclaw-scopes apenas limita os escopos negociados da sessão, não os concede. Consulte Comportamento de pareamento da UI de Controle.

    Exemplos:

    • x-openclaw-scopes: operator.read
    • x-openclaw-scopes: operator.read,operator.write
    • x-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 solicitação declara nenhum escopo de operador.
    • Quando o cabeçalho está ausente, as APIs HTTP normais que carregam identidade usam como fallback o conjunto padrão de escopos do operador (operator.admin, operator.read, operator.write, operator.approvals, operator.pairing, operator.talk.secrets).
    • As rotas HTTP de Plugins com autenticação pelo Gateway são mais restritas por padrão: quando x-openclaw-scopes está ausente, o escopo de tempo de execução usa como fallback somente operator.write.
    • Solicitações HTTP originadas do navegador ainda precisam passar por gateway.controlUi.allowedOrigins (ou pelo modo de fallback deliberado do cabeçalho Host), mesmo após a autenticação por proxy confiável ser bem-sucedida.

    Regra prática: envie x-openclaw-scopes explicitamente quando quiser que uma solicitação de proxy confiável seja mais restrita que os padrões ou quando uma rota de Plugin autenticada pelo Gateway precisar de algo mais forte que o escopo de gravação.

    Terminação TLS e HSTS

    Use um único ponto de terminação TLS e aplique o HSTS nele.

    Terminação TLS no proxy (recomendado)

    Quando seu proxy reverso gerenciar HTTPS para https://control.example.com, defina Strict-Transport-Security no proxy para esse domínio.

    • Adequado para implantações voltadas para a internet.
    • Mantém o certificado e a política de proteção do HTTP em um só lugar.
    • O OpenClaw pode permanecer em HTTP via loopback por trás do proxy.

    Exemplo de valor do cabeçalho:

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

    Terminação TLS no Gateway

    Se o próprio OpenClaw servir HTTPS diretamente (sem proxy de terminação TLS), defina:

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

    strictTransportSecurity aceita um valor de cabeçalho em formato de string ou false para desabilitá-lo explicitamente.

    Orientações para implantação

    • Comece 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 de obter alta confiança.
    • Adicione includeSubDomains somente se todos os subdomínios estiverem preparados para HTTPS.
    • Use a pré-carga somente se você atender intencionalmente aos requisitos de pré-carga para todo o conjunto de domínios.
    • O desenvolvimento local somente em loopback não se beneficia do HSTS.

    Exemplos de configuração de proxy

    Pomerium

    O Pomerium transmite a identidade em x-pomerium-claim-email (ou em outros cabeçalhos de declarações) e um JWT em x-pomerium-jwt-assertion.

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

    Trecho da configuração do Pomerium:

    yaml
    routes:  - from: https://openclaw.example.com    to: http://openclaw-gateway:18789    policy:      - allow:          or:            - email:                is: nick@example.com    pass_identity_headers: true
    Caddy com OAuth

    O Caddy com o Plugin caddy-security pode autenticar usuários e transmitir cabeçalhos de identidade.

    json5
    {  gateway: {    bind: "lan",    trustedProxies: ["10.0.0.1"], // Caddy/sidecar proxy IP    auth: {      mode: "trusted-proxy",      trustedProxy: {        userHeader: "x-forwarded-user",      },    },  },}

    Trecho do Caddyfile:

    caddy
    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 os usuários e transmite a identidade em x-auth-request-email.

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

    Trecho da configuração do nginx:

    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 autenticação encaminhada
    json5
    {  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

    A inicialização do Gateway rejeita a autenticação por proxy confiável se um token compartilhado também estiver configurado (gateway.auth.token ou OPENCLAW_GATEWAY_TOKEN). As duas opções são mutuamente exclusivas, pois um token compartilhado permitiria que chamadores no mesmo host se autenticassem por um caminho totalmente diferente da identidade verificada pelo proxy que este modo deve impor.

    Se a inicialização falhar com um erro como gateway auth mode is trusted-proxy, but a shared token is also configured:

    • Remova o token compartilhado ao usar o modo de proxy confiável; ou
    • Altere gateway.auth.mode para "token" se você pretende usar autenticação baseada em token.

    Os cabeçalhos de identidade do proxy confiável em local loopback ainda falham de forma restritiva: chamadores no mesmo host não são autenticados silenciosamente como usuários do proxy. Chamadores internos do OpenClaw que ignoram o proxy podem se autenticar com gateway.auth.password / OPENCLAW_GATEWAY_PASSWORD. O fallback para token continua intencionalmente sem suporte no modo de proxy confiável.

    Lista de verificação de segurança

    Antes de habilitar a autenticação por proxy confiável, verifique:

    • [ ] O proxy é o único caminho: a porta do Gateway está protegida por firewall contra tudo, exceto seu proxy.
    • [ ] trustedProxies é mínimo: somente os IPs reais do seu proxy, não sub-redes inteiras.
    • [ ] A origem local loopback do proxy é intencional: a autenticação por proxy confiável falha de forma restritiva para solicitações originadas de loopback, a menos que gateway.auth.trustedProxy.allowLoopback seja explicitamente habilitado para um proxy no mesmo host.
    • [ ] O proxy remove cabeçalhos: seu proxy sobrescreve (não acrescenta) cabeçalhos x-forwarded-* enviados pelos clientes.
    • [ ] Encerramento de TLS: seu proxy gerencia o TLS; os usuários se conectam via HTTPS.
    • [ ] allowedOrigins é explícito: a Control UI fora de loopback usa gateway.controlUi.allowedOrigins explícito.
    • [ ] allowUsers está definido (recomendado): restrinja o acesso a usuários conhecidos, em vez de permitir qualquer pessoa autenticada.
    • [ ] Nenhuma configuração mista de token: não defina simultaneamente gateway.auth.token e gateway.auth.mode: "trusted-proxy".
    • [ ] O fallback de senha local é privado: se você configurar gateway.auth.password para chamadores internos diretos, mantenha a porta do Gateway protegida por firewall para que clientes remotos que não passam pelo proxy não possam acessá-la diretamente.

    Auditoria de segurança

    openclaw security audit sinaliza a autenticação por proxy confiável com uma constatação de severidade crítica. Isso é intencional; serve como lembrete de que você está delegando a segurança à configuração do seu proxy.

    A auditoria verifica:

    • Aviso/lembrete crítico básico de gateway.trusted_proxy_auth.
    • Ausência da configuração trustedProxies.
    • Ausência da configuração userHeader.
    • allowUsers vazio (permite qualquer usuário autenticado).
    • allowLoopback habilitado para origens de proxy no mesmo host.

    Constatações separadas e não específicas de proxy confiável também se aplicam sempre que a Control UI está exposta: gateway.controlUi.allowedOrigins ausente ou com curinga e fallback de origem baseado no cabeçalho Host.

    Solução de problemas

    trusted_proxy_untrusted_source

    A solicitação não veio de um IP presente em gateway.trustedProxies. Verifique:

    • O IP do proxy está correto? (Os IPs de contêineres Docker podem mudar.)
    • Há um balanceador de carga à frente do seu proxy?
    • Use docker inspect ou kubectl get pods -o wide para encontrar os IPs reais.
    trusted_proxy_loopback_source

    O OpenClaw rejeitou uma solicitação de proxy confiável originada de 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
    • Encaminhe o tráfego 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 intencional no mesmo host, defina gateway.auth.trustedProxy.allowLoopback = true, mantenha o endereço de loopback em gateway.trustedProxies e garanta que o proxy remova ou sobrescreva os cabeçalhos de identidade.
    trusted_proxy_local_interface_source / trusted_proxy_local_interface_check_failed

    O IP de origem da solicitação correspondeu a um dos endereços das interfaces de rede do próprio host do Gateway que não são loopback (não ao proxy), uma proteção contra tráfego falsificado no mesmo host em tailnets ou redes bridge do Docker. ..._check_failed significa que a própria descoberta de interfaces apresentou erro, portanto o OpenClaw falha de forma restritiva.

    Verifique:

    • Um processo no próprio host do Gateway está enviando cabeçalhos de identidade diretamente, ignorando o proxy?
    • O proxy é executado no mesmo namespace de rede que o Gateway, com um IP que também aparece como uma interface local?

    Correção: encaminhe o tráfego do proxy por um endereço que também não esteja vinculado localmente pelo host do Gateway ou use allowLoopback somente para uma configuração genuína de proxy no mesmo host.

    trusted_proxy_user_missing

    O cabeçalho do usuário estava vazio ou ausente. Verifique:

    • Seu proxy está configurado para transmitir 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_no_proxies_configured / trusted_proxy_config_missing

    gateway.auth.mode é "trusted-proxy", mas gateway.trustedProxies está vazio, ou o próprio gateway.auth.trustedProxy está ausente. Todas as solicitações são rejeitadas até que ambos sejam definidos.

    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.allowedOrigins inclui a origem exata do navegador.
    • Você não depende de origens com curinga, a menos que queira intencionalmente permitir todas as origens.
    • Se você usa intencionalmente o modo de fallback baseado no cabeçalho Host, gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback=true foi definido deliberadamente.
    A conexão é bem-sucedida, mas os métodos informam escopo ausente

    O WebSocket se 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 permitir a conexão WebSocket sem uma identidade de dispositivo, mas o OpenClaw remove os escopos de sessões sem dispositivo por design.
    • Cliente de backend personalizado: gateway.controlUi.dangerouslyDisableDeviceAuth é limitado à Control UI e não concede escopos a clientes WebSocket arbitrários de backend ou com formato de CLI.
    • x-openclaw-scopes excessivamente restrito: se o proxy injetar esse cabeçalho na solicitação de atualização do WebSocket da Control UI, os escopos da sessão serão limitados a esse conjunto. Um valor de cabeçalho vazio não concede nenhum escopo.

    Correção:

    • Para a Control UI, use HTTPS para que o navegador possa gerar uma identidade de dispositivo e concluir o pareamento.
    • Para automação personalizada, use identidade de dispositivo/pareamento, o caminho auxiliar reservado de backend local direto gateway-client ou o RPC HTTP administrativo.
    • Use gateway.controlUi.dangerouslyDisableDeviceAuth: true somente como um recurso temporário de emergência para a Control UI.
    O WebSocket continua falhando

    Certifique-se de que seu proxy:

    • Ofereça suporte a atualizações de WebSocket (Upgrade: websocket, Connection: upgrade).
    • Transmita os cabeçalhos de identidade nas solicitações de atualização de WebSocket (não apenas em HTTP).
    • Não tenha um caminho de autenticação separado para conexões WebSocket.

    Migração da autenticação por token

  • Configurar o proxy

    Configure seu proxy para autenticar usuários e transmitir cabeçalhos.

  • Testar o proxy de forma independente

    Teste a configuração do proxy de forma independente (curl com cabeçalhos).

  • Atualizar a configuração do OpenClaw

    Atualize a configuração do OpenClaw com autenticação por proxy confiável.

  • Reiniciar o Gateway

    Reinicie o Gateway.

  • Testar o WebSocket

    Teste as conexões WebSocket da Control UI.

  • Auditar

    Execute openclaw security audit e analise as constatações.

  • Relacionado

    Was this useful?
    On this page

    On this page