Cuándo usarlo
- Ejecutas OpenClaw detrás de un proxy con reconocimiento de identidad (Pomerium, Caddy + OAuth, nginx + oauth2-proxy, Traefik + forward auth).
- Tu proxy gestiona toda la autenticación y pasa la identidad del usuario mediante encabezados.
- Estás en un entorno de Kubernetes o contenedores donde el proxy es la única ruta hacia el Gateway.
- Te encuentras con errores WebSocket
1008 unauthorizedporque los navegadores no pueden pasar tokens en cargas útiles de WS.
Cuándo NO usarlo
- Tu proxy no autentica usuarios (solo es un terminador TLS o balanceador de carga).
- Hay alguna ruta hacia el Gateway que evita el proxy (huecos de firewall, acceso de red interno).
- No tienes certeza de que tu proxy elimine o sobrescriba correctamente los encabezados reenviados.
- Solo necesitas acceso personal de un único usuario (considera Tailscale Serve + loopback en su lugar).
Cómo funciona
Proxy adds an identity header
x-forwarded-user: nick@example.com).Gateway verifies trusted source
gateway.trustedProxies) y que no sea la propia dirección de loopback o de interfaz local del Gateway.Gateway extracts identity
Configuración
Referencia de configuración
"trusted-proxy".Comportamiento de emparejamiento de Control UI
Cuandogateway.auth.mode = "trusted-proxy" está activo y la solicitud supera las comprobaciones de proxy de confianza, las sesiones WebSocket de Control UI pueden conectarse sin identidad de emparejamiento de dispositivo.
Implicaciones de alcance:
- Las sesiones WebSocket de Control UI sin dispositivo se conectan, pero no reciben alcances de operador de forma predeterminada. OpenClaw borra la lista de alcances solicitados a
[]para que una sesión no vinculada a un dispositivo/token emparejado aprobado no pueda autodeclarar permisos. - Si los métodos fallan con
missing scopedespués de una conexión WebSocket correcta, usa HTTPS para que el navegador pueda generar identidad de dispositivo y completar el emparejamiento. Consulta HTTP inseguro de Control UI. - Solo para emergencia:
gateway.controlUi.dangerouslyDisableDeviceAuth=trueconserva los alcances solicitados incluso sin identidad de dispositivo. Esto es una degradación de seguridad grave; reviértelo rápidamente. Consulta HTTP inseguro de Control UI.
x-openclaw-scopes en la solicitud de actualización WebSocket de Control UI, OpenClaw limita los alcances de la sesión a la intersección de los alcances solicitados y los alcances declarados. Este encabezado no concede alcances; solo restringe lo que la sesión puede tener.
Implicaciones:
- El emparejamiento ya no es la puerta principal para el acceso a Control UI en este modo.
- La política de autenticación de tu proxy inverso y
allowUsersse convierten en el control de acceso efectivo. - Mantén la entrada al Gateway bloqueada solo para IP de proxy de confianza (
gateway.trustedProxies+ firewall).
gateway.controlUi.dangerouslyDisableDeviceAuth no concede alcances a clientes arbitrarios con client.mode: "backend" o con forma de CLI. La automatización personalizada debe usar identidad/emparejamiento de dispositivo, la ruta auxiliar backend local directa reservada client.id: "gateway-client" o el Plugin admin HTTP RPC cuando una superficie HTTP de solicitud/respuesta encaje mejor.
Encabezado de alcances de operador
La autenticación de proxy de confianza es un modo HTTP portador de identidad, por lo que los llamadores pueden declarar opcionalmente alcances de operador conx-openclaw-scopes en solicitudes de API HTTP.
Nota: los alcances de WebSocket se determinan mediante el handshake del protocolo del Gateway y la vinculación de identidad de dispositivo. En solicitudes de actualización WebSocket de Control UI, x-openclaw-scopes solo es un límite sobre los alcances de sesión negociados, no una concesión. Consulta Comportamiento de emparejamiento de Control UI.
Ejemplos:
x-openclaw-scopes: operator.readx-openclaw-scopes: operator.read,operator.writex-openclaw-scopes: operator.admin,operator.write
- Cuando el encabezado está presente, OpenClaw respeta el conjunto de alcances declarado.
- Cuando el encabezado está presente pero vacío, la solicitud declara ningún alcance de operador.
- Cuando el encabezado está ausente, las API HTTP normales portadoras de identidad recurren al conjunto de alcances de operador predeterminado estándar (
operator.admin,operator.read,operator.write,operator.approvals,operator.pairing,operator.talk.secrets). - Las rutas HTTP de Plugin con autenticación de Gateway son más restringidas de forma predeterminada: cuando
x-openclaw-scopesestá ausente, su alcance de ejecución recurre solo aoperator.write. - Las solicitudes HTTP con origen de navegador aún tienen que pasar
gateway.controlUi.allowedOrigins(o el modo deliberado de respaldo por encabezado Host) incluso después de que la autenticación de proxy de confianza tenga éxito.
x-openclaw-scopes explícitamente cuando quieras que una solicitud de proxy de confianza sea más restringida que los valores predeterminados, o cuando una ruta de Plugin con autenticación de Gateway necesite algo más fuerte que el alcance de escritura.
Terminación TLS y HSTS
Usa un solo punto de terminación TLS y aplica HSTS allí.- Proxy TLS termination (recommended)
- Gateway TLS termination
https://control.example.com, configura Strict-Transport-Security en el proxy para ese dominio.- Buena opción para despliegues expuestos a Internet.
- Mantiene la política de certificados y endurecimiento HTTP en un solo lugar.
- OpenClaw puede permanecer en HTTP de loopback detrás del proxy.
Guía de despliegue gradual
- Empieza primero con una duración máxima corta (por ejemplo,
max-age=300) mientras validas el tráfico. - Aumenta a valores de larga duración (por ejemplo,
max-age=31536000) solo después de tener alta confianza. - Agrega
includeSubDomainssolo si todos los subdominios están listos para HTTPS. - Usa preload solo si cumples intencionadamente los requisitos de preload para todo tu conjunto de dominios.
- El desarrollo local solo con loopback no se beneficia de HSTS.
Ejemplos de configuración de proxy
Pomerium
Pomerium
x-pomerium-claim-email (u otros encabezados de reclamación) y un JWT en x-pomerium-jwt-assertion.Caddy with OAuth
Caddy with OAuth
caddy-security puede autenticar usuarios y pasar encabezados de identidad.nginx + oauth2-proxy
nginx + oauth2-proxy
x-auth-request-email.Traefik con autenticación reenviada
Traefik con autenticación reenviada
Configuración mixta de tokens
El arranque del Gateway rechaza la autenticación trusted-proxy si también se configura un token compartido (gateway.auth.token u OPENCLAW_GATEWAY_TOKEN). Ambos son mutuamente excluyentes porque un token compartido permitiría que los llamadores del mismo host se autentiquen por una ruta completamente distinta de la identidad verificada por el proxy que este modo pretende imponer.
Si el arranque falla con un error como gateway auth mode is trusted-proxy, but a shared token is also configured:
- Elimina el token compartido al usar el modo trusted-proxy, o
- Cambia
gateway.auth.modea"token"si quieres usar autenticación basada en token.
gateway.auth.password / OPENCLAW_GATEWAY_PASSWORD en su lugar. La alternativa de token sigue sin estar admitida intencionalmente en modo trusted-proxy.
Lista de verificación de seguridad
Antes de habilitar la autenticación trusted-proxy, verifica:- El proxy es la única ruta: el puerto del Gateway está protegido por firewall frente a todo salvo tu proxy.
- trustedProxies es mínimo: solo las IP reales de tu proxy, no subredes completas.
- El origen de proxy desde loopback es deliberado: la autenticación trusted-proxy falla en modo cerrado para solicitudes con origen de loopback a menos que
gateway.auth.trustedProxy.allowLoopbackesté habilitado explícitamente para un proxy en el mismo host. - El proxy elimina encabezados: tu proxy sobrescribe (no agrega) los encabezados
x-forwarded-*de los clientes. - Terminación TLS: tu proxy gestiona TLS; los usuarios se conectan mediante HTTPS.
- allowedOrigins es explícito: Control UI fuera de loopback usa
gateway.controlUi.allowedOriginsexplícito. - allowUsers está definido (recomendado): restringe el acceso a usuarios conocidos en lugar de permitir a cualquiera que esté autenticado.
- Sin configuración mixta de tokens: no definas tanto
gateway.auth.tokencomogateway.auth.mode: "trusted-proxy". - La alternativa de contraseña local es privada: si configuras
gateway.auth.passwordpara llamadores internos directos, mantén el puerto del Gateway protegido por firewall para que los clientes remotos que no pasan por el proxy no puedan alcanzarlo directamente.
Auditoría de seguridad
openclaw security audit marca la autenticación trusted-proxy con un hallazgo de gravedad crítica. Esto es intencional; es un recordatorio de que estás delegando la seguridad a la configuración de tu proxy.
La auditoría comprueba:
- Advertencia/recordatorio crítico base
gateway.trusted_proxy_auth. - Falta de configuración de
trustedProxies. - Falta de configuración de
userHeader. allowUsersvacío (permite cualquier usuario autenticado).allowLoopbackhabilitado para orígenes de proxy en el mismo host.
gateway.controlUi.allowedOrigins comodín o ausente, y alternativa de origen mediante encabezado Host.
Solución de problemas
trusted_proxy_untrusted_source
trusted_proxy_untrusted_source
gateway.trustedProxies. Comprueba:- ¿La IP del proxy es correcta? (Las IP de contenedores Docker pueden cambiar.)
- ¿Hay un balanceador de carga delante de tu proxy?
- Usa
docker inspectokubectl get pods -o widepara encontrar las IP reales.
trusted_proxy_loopback_source
trusted_proxy_loopback_source
- ¿El proxy se conecta desde
127.0.0.1/::1? - ¿Intentas usar autenticación trusted-proxy con un proxy inverso de loopback en el mismo host?
- Prefiere autenticación por token/contraseña para clientes internos del mismo host que no pasan por el proxy, o
- Enruta a través de una dirección de proxy confiable que no sea loopback y conserva esa IP en
gateway.trustedProxies, o - Para un proxy inverso deliberado en el mismo host, define
gateway.auth.trustedProxy.allowLoopback = true, conserva la dirección de loopback engateway.trustedProxiesy asegúrate de que el proxy elimine o sobrescriba los encabezados de identidad.
trusted_proxy_local_interface_source / trusted_proxy_local_interface_check_failed
trusted_proxy_local_interface_source / trusted_proxy_local_interface_check_failed
..._check_failed significa que el propio descubrimiento de interfaces produjo un error, por lo que OpenClaw falla en modo cerrado.Comprueba:- ¿Un proceso en el propio host del Gateway envía encabezados de identidad directamente, omitiendo el proxy?
- ¿El proxy se ejecuta en el mismo espacio de nombres de red que el Gateway, con una IP que también aparece como interfaz local?
allowLoopback solo para una configuración genuina de proxy en el mismo host.trusted_proxy_user_missing
trusted_proxy_user_missing
- ¿Tu proxy está configurado para pasar encabezados de identidad?
- ¿El nombre del encabezado es correcto? (no distingue mayúsculas y minúsculas, pero la ortografía importa)
- ¿El usuario está realmente autenticado en el proxy?
trusted_proxy_missing_header_*
trusted_proxy_missing_header_*
- La configuración de tu proxy para esos encabezados específicos.
- Si los encabezados se están eliminando en algún punto de la cadena.
trusted_proxy_user_not_allowed
trusted_proxy_user_not_allowed
allowUsers. Agrégalo o elimina la lista de permitidos.trusted_proxy_no_proxies_configured / trusted_proxy_config_missing
trusted_proxy_no_proxies_configured / trusted_proxy_config_missing
gateway.auth.mode es "trusted-proxy", pero gateway.trustedProxies está vacío, o falta el propio gateway.auth.trustedProxy. Todas las solicitudes se rechazan hasta que ambos estén configurados.trusted_proxy_origin_not_allowed
trusted_proxy_origin_not_allowed
Origin del navegador no pasó las comprobaciones de origen de Control UI.Comprueba:gateway.controlUi.allowedOriginsincluye el origen exacto del navegador.- No dependes de orígenes comodín a menos que quieras intencionalmente un comportamiento de permitir todo.
- Si usas intencionalmente el modo de alternativa mediante encabezado Host,
gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback=trueestá definido deliberadamente.
La conexión se realiza correctamente, pero los métodos informan que falta el ámbito
La conexión se realiza correctamente, pero los métodos informan que falta el ámbito
chat.history, sessions.list o
models.list falla con missing scope: operator.read.Causas comunes:- Sesión de Control UI sin dispositivo: la autenticación trusted-proxy puede admitir la conexión WebSocket sin identidad de dispositivo, pero OpenClaw elimina los ámbitos en las sesiones sin dispositivo por diseño.
- Cliente backend personalizado:
gateway.controlUi.dangerouslyDisableDeviceAuthestá limitado a Control UI y no concede ámbitos a clientes WebSocket arbitrarios con forma de backend o CLI. x-openclaw-scopesdemasiado restringido: si tu proxy inyecta este encabezado en la solicitud de upgrade WebSocket de Control UI, los ámbitos de la sesión quedan limitados a ese conjunto. Un valor de encabezado vacío produce cero ámbitos.
- Para Control UI, usa HTTPS para que el navegador pueda generar la identidad de dispositivo y completar el emparejamiento.
- Para automatización personalizada, usa identidad/emparejamiento de dispositivo, la ruta auxiliar backend reservada directa-local
gateway-cliento RPC HTTP de administración. - Usa
gateway.controlUi.dangerouslyDisableDeviceAuth: truesolo como una ruta temporal de emergencia para Control UI.
WebSocket sigue fallando
WebSocket sigue fallando
- Admita upgrades de WebSocket (
Upgrade: websocket,Connection: upgrade). - Pase los encabezados de identidad en solicitudes de upgrade WebSocket (no solo HTTP).
- No tenga una ruta de autenticación separada para conexiones WebSocket.
Migración desde autenticación por token
Probar el proxy de forma independiente
Actualizar la configuración de OpenClaw
Relacionado
- Configuración — referencia de configuración
- Ámbitos de operador — roles, ámbitos y comprobaciones de aprobación
- Acceso remoto — otros patrones de acceso remoto
- Seguridad — guía de seguridad completa
- Tailscale — alternativa más simple para acceso solo por tailnet