快速开始
受信任代理身份验证
何时使用
在以下情况下使用 trusted-proxy 认证模式:
- 你在可识别身份的代理(Pomerium、Caddy + OAuth、nginx + oauth2-proxy、Traefik + forward auth)后运行 OpenClaw。
- 你的代理处理所有身份验证,并通过标头传递用户身份。
- 你处于 Kubernetes 或容器环境中,代理是通向 Gateway 网关的唯一路径。
- 你遇到 WebSocket
1008 unauthorized错误,因为浏览器无法在 WS 载荷中传递令牌。
何时不要使用
- 如果你的代理不会对用户进行身份验证(只是 TLS 终结器或负载均衡器)。
- 如果存在任何绕过代理通向 Gateway 网关的路径(防火墙漏洞、内部网络访问)。
- 如果你不确定代理是否正确剥离/覆盖转发标头。
- 如果你只需要个人单用户访问(可考虑使用 Tailscale Serve + loopback 来简化设置)。
工作原理
Proxy authenticates the user
你的反向代理会对用户进行身份验证(OAuth、OIDC、SAML 等)。
Proxy adds an identity header
代理会添加一个包含已认证用户身份的标头(例如 x-forwarded-user: [email protected])。
Gateway verifies trusted source
OpenClaw 会检查请求是否来自受信任的代理 IP(在 gateway.trustedProxies 中配置)。
Gateway extracts identity
OpenClaw 会从配置的标头中提取用户身份。
Authorize
如果所有检查都通过,请求会被授权。
Control UI 配对行为
当 gateway.auth.mode = "trusted-proxy" 处于启用状态且请求通过 trusted-proxy 检查时,Control UI WebSocket 会话无需设备配对身份即可连接。
影响:
- 在此模式下,配对不再是 Control UI 访问的主要关口。
- 你的反向代理认证策略和
allowUsers会成为实际的访问控制。 - 仅允许受信任的代理 IP 进入 Gateway 网关入口(
gateway.trustedProxies+ 防火墙)。
配置
{
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: ["[email protected]", "[email protected]"],
// Optional: allow a same-host loopback proxy after explicit opt-in
allowLoopback: false,
},
},
},
}
配置参考
gateway.trustedProxiesstring[]required要信任的代理 IP 地址数组。来自其他 IP 的请求会被拒绝。
gateway.auth.modestringrequired必须为 "trusted-proxy"。
gateway.auth.trustedProxy.userHeaderstringrequired包含已认证用户身份的标头名称。
gateway.auth.trustedProxy.requiredHeadersstring[]请求必须存在的额外标头,存在后请求才会被信任。
gateway.auth.trustedProxy.allowUsersstring[]用户身份允许列表。为空表示允许所有已认证用户。
gateway.auth.trustedProxy.allowLoopbackboolean对同主机 loopback 反向代理的显式启用支持。默认为 false。
TLS 终止与 HSTS
使用一个 TLS 终止点,并在那里应用 HSTS。
Proxy TLS termination (recommended)
当你的反向代理为 https://control.example.com 处理 HTTPS 时,请在代理上为该域设置 Strict-Transport-Security。
- 适合面向互联网的部署。
- 将证书和 HTTP 加固策略保留在一个位置。
- OpenClaw 可以在代理后继续使用 loopback HTTP。
示例标头值:
Strict-Transport-Security: max-age=31536000; includeSubDomains
Gateway TLS termination
如果 OpenClaw 本身直接提供 HTTPS(没有终止 TLS 的代理),请设置:
{
gateway: {
tls: { enabled: true },
http: {
securityHeaders: {
strictTransportSecurity: "max-age=31536000; includeSubDomains",
},
},
},
}
strictTransportSecurity 接受字符串标头值,或使用 false 显式禁用。
推出指南
- 验证流量时,先从较短的最大期限开始(例如
max-age=300)。 - 只有在信心较高后,才增加到长期值(例如
max-age=31536000)。 - 只有当每个子域都已准备好使用 HTTPS 时,才添加
includeSubDomains。 - 只有当你有意为完整域集合满足 preload 要求时,才使用 preload。
- 仅限 loopback 的本地开发不会从 HSTS 中受益。
代理设置示例
Pomerium
Pomerium 通过 x-pomerium-claim-email(或其他声明标头)传递身份,并通过 x-pomerium-jwt-assertion 传递 JWT。
{
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"],
},
},
},
}
Pomerium 配置片段:
routes:
- from: https://openclaw.example.com
to: http://openclaw-gateway:18789
policy:
- allow:
or:
- email:
is: [email protected]
pass_identity_headers: true
Caddy with OAuth
带有 caddy-security 插件的 Caddy 可以对用户进行身份验证并传递身份标头。
{
gateway: {
bind: "lan",
trustedProxies: ["10.0.0.1"], // Caddy/sidecar proxy IP
auth: {
mode: "trusted-proxy",
trustedProxy: {
userHeader: "x-forwarded-user",
},
},
},
}
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 会对用户进行身份验证,并通过 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 配置片段:
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",
},
},
},
}
混合令牌配置
OpenClaw 会拒绝同时启用 gateway.auth.token(或 OPENCLAW_GATEWAY_TOKEN)和 trusted-proxy 模式的歧义配置。混合令牌配置可能导致 loopback 请求在错误的认证路径上被静默认证。
如果你在启动时看到 mixed_trusted_proxy_token 错误:
- 使用 trusted-proxy 模式时移除共享令牌,或
- 如果你打算使用基于令牌的认证,请将
gateway.auth.mode切换为"token"。
Loopback trusted-proxy 身份标头仍会失败关闭:同主机调用方不会被静默认证为代理用户。绕过代理的内部 OpenClaw 调用方可改用 gateway.auth.password / OPENCLAW_GATEWAY_PASSWORD 进行认证。在 trusted-proxy 模式下,令牌回退仍被有意不支持。
操作员作用域标头
Trusted-proxy 认证是一种携带身份的 HTTP 模式,因此调用方可以选择使用 x-openclaw-scopes 声明操作员作用域。
示例:
x-openclaw-scopes: operator.readx-openclaw-scopes: operator.read,operator.writex-openclaw-scopes: operator.admin,operator.write
行为:
- 当标头存在时,OpenClaw 会遵循声明的作用域集合。
- 当标头存在但为空时,请求声明没有操作员作用域。
- 当标头不存在时,普通的携带身份 HTTP API 会回退到标准操作员默认作用域集合。
- Gateway 网关认证的插件 HTTP 路由默认范围更窄:当
x-openclaw-scopes不存在时,其运行时作用域会回退到operator.write。 - 即使 trusted-proxy 认证成功,来自浏览器来源的 HTTP 请求仍必须通过
gateway.controlUi.allowedOrigins(或有意启用的 Host 标头回退模式)。
实用规则:当你希望 trusted-proxy 请求比默认值更窄,或当 Gateway 网关认证的插件路由需要比写入作用域更强的权限时,请显式发送 x-openclaw-scopes。
安全检查清单
启用受信代理认证前,请确认:
- [ ] 代理是唯一访问路径:除你的代理之外,Gateway 网关端口已对所有其他来源加防火墙。
- [ ] trustedProxies 保持最小化:只包含你的实际代理 IP,而不是整个子网。
- [ ] 回环代理来源是有意配置的:除非为同主机代理显式启用
gateway.auth.trustedProxy.allowLoopback,否则受信代理认证会对回环来源请求默认拒绝。 - [ ] 代理会剥离标头:你的代理会覆盖(而不是追加)来自客户端的
x-forwarded-*标头。 - [ ] TLS 终止:你的代理处理 TLS;用户通过 HTTPS 连接。
- [ ] allowedOrigins 已显式设置:非回环 Control UI 使用显式的
gateway.controlUi.allowedOrigins。 - [ ] allowUsers 已设置(推荐):限制为已知用户,而不是允许任何已认证用户。
- [ ] 没有混用令牌配置:不要同时设置
gateway.auth.token和gateway.auth.mode: "trusted-proxy"。 - [ ] 本地密码回退保持私有:如果你为内部直连调用方配置
gateway.auth.password,请保持 Gateway 网关端口受防火墙保护,使非代理远程客户端无法直接访问它。
安全审计
openclaw security audit 会将受信代理认证标记为严重级别发现。这是有意设计的,用于提醒你:你正在把安全性交给你的代理设置。
审计会检查:
- 基础
gateway.trusted_proxy_auth警告/严重提醒 - 缺少
trustedProxies配置 - 缺少
userHeader配置 allowUsers为空(允许任何已认证用户)- 为同主机代理来源启用了
allowLoopback - 暴露的 Control UI 表面使用通配符或缺少浏览器来源策略
故障排除
trusted_proxy_untrusted_source
请求并非来自 gateway.trustedProxies 中的 IP。请检查:
- 代理 IP 是否正确?(Docker 容器 IP 可能会变化。)
- 你的代理前面是否有负载均衡器?
- 使用
docker inspect或kubectl get pods -o wide查找实际 IP。
trusted_proxy_loopback_source
OpenClaw 拒绝了一个回环来源的受信代理请求。
检查:
- 代理是否从
127.0.0.1/::1连接? - 你是否在尝试将受信代理认证与同主机回环反向代理一起使用?
修复:
- 对于不经过代理的内部同主机客户端,优先使用令牌/密码认证,或
- 通过非回环的受信代理地址路由,并将该 IP 保持在
gateway.trustedProxies中,或 - 对于有意配置的同主机反向代理,设置
gateway.auth.trustedProxy.allowLoopback = true,将回环地址保留在gateway.trustedProxies中,并确保代理会剥离或覆盖身份标头。
trusted_proxy_user_missing
用户标头为空或缺失。请检查:
- 你的代理是否配置为传递身份标头?
- 标头名称是否正确?(不区分大小写,但拼写很重要)
- 用户是否确实已在代理处认证?
trusted_proxy_missing_header_*
必需标头不存在。请检查:
- 你的代理中这些特定标头的配置。
- 标头是否在链路中的某处被剥离。
trusted_proxy_user_not_allowed
用户已认证,但不在 allowUsers 中。请添加该用户,或移除允许列表。
trusted_proxy_origin_not_allowed
受信代理认证成功,但浏览器 Origin 标头未通过 Control UI 来源检查。
检查:
gateway.controlUi.allowedOrigins包含精确的浏览器来源。- 除非你有意需要允许所有行为,否则不要依赖通配符来源。
- 如果你有意使用 Host 标头回退模式,已明确设置
gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback=true。
WebSocket 仍然失败
确保你的代理:
- 支持 WebSocket 升级(
Upgrade: websocket、Connection: upgrade)。 - 在 WebSocket 升级请求中传递身份标头(不只是 HTTP)。
- 没有为 WebSocket 连接使用单独的认证路径。
从令牌认证迁移
如果你正在从令牌认证迁移到受信代理:
配置代理
配置你的代理来认证用户并传递标头。
独立测试代理
独立测试代理设置(使用带标头的 curl)。
更新 OpenClaw 配置
使用受信代理认证更新 OpenClaw 配置。
重启 Gateway 网关
重启 Gateway 网关。
测试 WebSocket
从 Control UI 测试 WebSocket 连接。
审计
运行 openclaw security audit 并查看发现。