何时使用
- 你在身份感知代理(Pomerium、Caddy + OAuth、nginx + oauth2-proxy、Traefik + forward auth)后运行 OpenClaw。
- 你的代理处理所有身份验证,并通过请求头传递用户身份。
- 你使用 Kubernetes 或容器环境,且代理是访问 Gateway 网关的唯一路径。
- 由于浏览器无法在 WS 载荷中传递令牌,你遇到了 WebSocket
1008 unauthorized错误。
不应使用的情况
- 你的代理不验证用户身份(仅作为 TLS 终止器或负载均衡器)。
- 存在任何绕过代理访问 Gateway 网关的路径(防火墙漏洞、内部网络访问)。
- 你不确定代理是否正确移除或覆盖转发请求头。
- 你只需要个人单用户访问(可考虑改用 Tailscale Serve + loopback)。
工作原理
1
代理验证用户身份
反向代理验证用户身份(OAuth、OIDC、SAML 等)。
2
代理添加身份请求头
代理添加一个包含已验证用户身份的请求头(例如
x-forwarded-user: nick@example.com)。3
Gateway 网关验证可信来源
OpenClaw 检查请求是否来自可信代理 IP(
gateway.trustedProxies),并确认其不是 Gateway 网关自身的 loopback 或本地接口地址。4
Gateway 网关提取身份
OpenClaw 读取必需请求头,然后从配置的请求头中读取用户身份。
5
授权
如果所有检查均通过,且用户通过
allowUsers 检查(如已设置),则授权该请求。配置
配置参考
string[]
必填
要信任的代理 IP 地址(或 CIDR)数组。来自其他 IP 的请求将被拒绝。
string
必填
必须为
"trusted-proxy"。string
必填
包含已验证用户身份的请求头名称。
string[]
要信任请求必须存在的其他请求头。
string[]
用户身份允许列表。为空表示允许所有已验证身份的用户。
boolean
默认值:"false"
选择启用对同一主机上 loopback 反向代理的支持。
boolean
默认值:"false"
在可信代理身份验证后,自动批准新的 Control UI 和 WebChat 设备身份。
string[]
授予自动批准的浏览器设备的最大权限范围。显式列出
operator.admin 后,每个通过代理验证身份的用户都可以请求自动授予设备完整管理员权限;未指定权限范围的请求会自动获得完整管理员权限;同时还会触发严重级别的 gateway.trusted_proxy_device_auto_approve_admin 安全审计发现和 Gateway 网关启动警告。自动批准设备
可信代理身份验证可以选择将代理身份用作新浏览器设备的批准边界:enabled: false。启用后,以下所有规则均适用:
- WebSocket 必须通过
trusted-proxy方法完成身份验证,具有非空用户身份,并且在配置了允许列表时通过allowUsers检查。令牌、密码、Tailscale 和未经身份验证的连接绝不会使用此策略。 - 只能自动批准新的 Control UI 或 WebChat 浏览器设备。对现有设备的任何请求(包括权限范围升级)仍会保持待处理状态,需使用
openclaw devices approve <requestId>手动批准。 - 设备以角色
operator获得批准。如果连接请求包含权限范围,授予的权限将是所请求权限范围与deviceAutoApprove.scopes的精确交集。如果请求省略权限范围,则授予配置的列表;省略该列表时,默认为operator.read、operator.write和operator.approvals。如果连接中存在x-openclaw-scopes代理请求头,最终授权还会受其进一步限制,因此代理缩小用户权限范围时,不仅会限制会话,还会限制持久化设备授权;如果请求头存在但值为空,则不会授予任何权限范围。即使客户端省略了自己的权限范围列表,此限制也仍然适用。 - 仅当在
deviceAutoApprove.scopes中显式列出时,才允许operator.admin。列出后,每个通过代理验证身份的用户都可以请求并自动获得新浏览器设备的完整管理员权限;未指定权限范围的请求会自动获得完整管理员权限。openclaw security audit会报告严重级别的gateway.trusted_proxy_device_auto_approve_admin发现,Gateway 网关还会在启动时记录一次警告。在按身份分配角色功能可用之前,建议通过openclaw devices approve或openclaw devices rotate手动批准管理员权限。
Control UI 配对行为
当gateway.auth.mode = "trusted-proxy" 处于启用状态且请求通过可信代理检查时,Control UI WebSocket 会话无需设备配对身份即可连接。
权限范围影响:
- 无设备身份的 Control UI WebSocket 会话可以连接,但默认不会获得任何操作员权限范围。OpenClaw 会将请求的权限范围列表清空为
[],从而防止未绑定到已批准配对设备或令牌的会话自行声明权限。 - 如果 WebSocket 成功连接后,方法调用因
missing scope而失败,请使用 HTTPS,以便浏览器生成设备身份并完成配对。请参阅 Control UI 不安全的 HTTP。 - 仍包含已停用的
gateway.controlUi.dangerouslyDisableDeviceAuth=true键的旧配置会使用受限的 Control UI 升级迁移。
x-openclaw-scopes,OpenClaw 会将会话权限范围限制为请求的权限范围与声明的权限范围的交集。此请求头不会授予权限范围;它只会缩小会话可持有的权限范围。当 deviceAutoApprove.enabled 为 true 时,同一上限也适用于由自动批准设备写入的持久化设备授权,因此自动批准的设备绝不会持有超过代理声明范围的权限。
影响:
- 配对不再是无设备身份的 Control UI 访问的主要门控。当
deviceAutoApprove.enabled为 true 时,代理身份也会成为新浏览器设备注册的批准门控。 - 你的反向代理身份验证策略和
allowUsers将成为实际的访问控制机制。 - 确保 Gateway 网关入口仅限可信代理 IP(
gateway.trustedProxies+ 防火墙)。
client.mode: "backend" 或 CLI 形式的客户端授予临时访问权限。自定义自动化应使用
设备身份/配对、预留的本地直连 client.id: "gateway-client"
后端辅助路径,或在 HTTP 请求/响应接口更合适时使用 admin HTTP RPC 插件。
操作员权限范围请求头
可信代理身份验证是一种携带身份信息的 HTTP 模式,因此调用方可以选择在 HTTP API 请求中通过x-openclaw-scopes 声明操作员权限范围。
注意:WebSocket 权限范围由 Gateway 网关协议握手和设备身份绑定决定。在 Control UI WebSocket 升级请求中,x-openclaw-scopes 只是协商所得会话权限范围的上限,并不会授予权限。请参阅 Control UI 配对行为。
示例:
x-openclaw-scopes: operator.readx-openclaw-scopes: operator.read,operator.writex-openclaw-scopes: operator.admin,operator.write
- 存在该请求头时,OpenClaw 会采用所声明的权限范围集合。
- 存在该请求头但其值为空时,请求声明不具有任何操作员权限范围。
- 缺少该请求头时,常规的携带身份信息 HTTP API 会回退到标准操作员默认权限范围集合(
operator.admin、operator.read、operator.write、operator.approvals、operator.pairing、operator.talk.secrets)。 - Gateway 网关身份验证的插件 HTTP 路由默认权限范围更窄:缺少
x-openclaw-scopes时,其运行时权限范围仅回退到operator.write。 - 即使可信代理身份验证成功,来自浏览器的 HTTP 请求仍必须通过
gateway.controlUi.allowedOrigins(或有意启用的 Host 请求头回退模式)。
x-openclaw-scopes。
TLS 终止和 HSTS
仅使用一个 TLS 终止点,并在该处应用 HSTS。- 代理 TLS 终止(推荐)
- Gateway 网关 TLS 终止
当反向代理为
https://control.example.com 处理 HTTPS 时,请在代理上为该域名设置 Strict-Transport-Security。- 非常适合面向互联网的部署。
- 将证书和 HTTP 安全强化策略集中在一处。
- OpenClaw 可以在代理后继续使用环回 HTTP。
推出指南
- 验证流量时,首先使用较短的最大有效期(例如
max-age=300)。 - 仅在信心充足后,才增加为长期有效值(例如
max-age=31536000)。 - 仅当所有子域名均已支持 HTTPS 时,才添加
includeSubDomains。 - 仅当你有意满足完整域名集合的预加载要求时,才使用预加载。
- 仅限环回的本地开发无法从 HSTS 中受益。
代理设置示例
Pomerium
Pomerium
Pomerium 通过 Pomerium 配置片段:
x-pomerium-claim-email(或其他声明请求头)传递身份,并通过 x-pomerium-jwt-assertion 传递 JWT。使用 OAuth 的 Caddy
使用 OAuth 的 Caddy
安装 Caddyfile 片段:
caddy-security 插件的 Caddy 可以对用户进行身份验证并传递身份请求头。nginx + oauth2-proxy
nginx + oauth2-proxy
oauth2-proxy 对用户进行身份验证,并通过 nginx 配置片段:
x-auth-request-email 传递身份。使用转发身份验证的 Traefik
使用转发身份验证的 Traefik
混合令牌配置
如果同时配置了共享令牌(gateway.auth.token 或 OPENCLAW_GATEWAY_TOKEN),Gateway 网关启动时会拒绝可信代理身份验证。两者互斥,因为共享令牌会让同一主机上的调用方通过一条与此模式旨在强制执行的代理验证身份完全不同的路径进行身份验证。
如果启动失败并出现类似 gateway auth mode is trusted-proxy, but a shared token is also configured 的错误:
- 使用可信代理模式时移除共享令牌,或者
- 如果你打算使用基于令牌的身份验证,请将
gateway.auth.mode切换为"token"。
gateway.auth.password / OPENCLAW_GATEWAY_PASSWORD 进行身份验证。在可信代理模式下,令牌回退仍被有意设为不支持。
安全检查清单
启用可信代理身份验证之前,请验证:- 代理是唯一路径:通过防火墙阻止除代理以外的所有对象访问 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 网关端口,确保非代理远程客户端无法直接访问。 - 设备自动批准经过有意配置:如果
deviceAutoApprove.enabled为 true,请将反向代理账户安全性视为设备注册边界,并确保授予的权限范围列表不包含管理员权限且保持最小范围。
安全审计
openclaw security audit 会以严重级别标记可信代理身份验证。这是有意设计的;它提醒你正在将安全性委托给代理设置。
审计会检查:
- 基础
gateway.trusted_proxy_auth警告/严重提醒。 - 缺少
trustedProxies配置。 - 缺少
userHeader配置。 allowUsers为空(允许任何已通过身份验证的用户)。- 为同一主机上的代理来源启用了
allowLoopback。 - 启用了浏览器设备自动批准(将新设备配对委托给代理身份)。
gateway.controlUi.allowedOrigins 使用通配符或缺失,以及 Host 请求头来源回退。
故障排查
trusted_proxy_untrusted_source
trusted_proxy_untrusted_source
请求并非来自
gateway.trustedProxies 中的 IP。请检查:- 代理 IP 是否正确?(Docker 容器 IP 可能会变化。)
- 代理前方是否存在负载均衡器?
- 使用
docker inspect或kubectl get pods -o wide查找实际 IP。
trusted_proxy_loopback_source
trusted_proxy_loopback_source
OpenClaw 拒绝了来自环回源的可信代理请求。请检查:
- 代理是否从
127.0.0.1/::1连接? - 你是否尝试通过同一主机上的环回反向代理使用可信代理身份验证?
- 对于不经过代理的同一主机内部客户端,优先使用令牌/密码身份验证,或者
- 通过非环回的可信代理地址进行路由,并将该 IP 保留在
gateway.trustedProxies中,或者 - 对于有意配置的同一主机反向代理,请设置
gateway.auth.trustedProxy.allowLoopback = true,将环回地址保留在gateway.trustedProxies中,并确保代理移除或覆盖身份请求头。
trusted_proxy_local_interface_source / trusted_proxy_local_interface_check_failed
trusted_proxy_local_interface_source / trusted_proxy_local_interface_check_failed
请求的源 IP 与 Gateway 网关主机自身的某个非环回网络接口地址(而非代理)匹配;这是一项防护措施,用于阻止 tailnet 或 Docker 桥接网络中同一主机流量的身份伪造。
..._check_failed 表示接口发现本身发生错误,因此 OpenClaw 会失败关闭。请检查:- Gateway 网关主机自身的某个进程是否绕过代理,直接发送身份请求头?
- 代理是否与 Gateway 网关运行在同一网络命名空间中,且其 IP 也显示为本地接口?
allowLoopback。trusted_proxy_user_missing
trusted_proxy_user_missing
用户请求头为空或缺失。请检查:
- 代理是否已配置为传递身份请求头?
- 请求头名称是否正确?(不区分大小写,但拼写必须正确)
- 用户是否确实已在代理处通过身份验证?
trusted_proxy_missing_header_*
trusted_proxy_missing_header_*
缺少必需的请求头。请检查:
- 代理中针对这些特定请求头的配置。
- 请求头是否在链路中的某处被移除。
trusted_proxy_user_not_allowed
trusted_proxy_user_not_allowed
用户已通过身份验证,但不在
allowUsers 中。请将其添加到允许列表,或移除该允许列表。trusted_proxy_no_proxies_configured / trusted_proxy_config_missing
trusted_proxy_no_proxies_configured / trusted_proxy_config_missing
gateway.auth.mode 为 "trusted-proxy",但 gateway.trustedProxies 为空,或 gateway.auth.trustedProxy 本身缺失。在两者均设置完成之前,所有请求都会被拒绝。trusted_proxy_origin_not_allowed
trusted_proxy_origin_not_allowed
可信代理身份验证成功,但浏览器的
Origin 标头未通过 Control UI 来源检查。请检查:gateway.controlUi.allowedOrigins包含准确的浏览器来源。- 除非有意允许所有来源,否则不要依赖通配符来源。
- 如果有意使用 Host 标头回退模式,请确保已明确设置
gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback=true。
连接成功,但方法报告缺少权限范围
连接成功,但方法报告缺少权限范围
WebSocket 已连接,但
chat.history、sessions.list 或
models.list 因 missing scope: operator.read 而失败。常见原因:- 无设备身份的 Control UI 会话:可信代理身份验证可以在没有设备身份的情况下允许建立 WebSocket 连接,但 OpenClaw 按设计会清除无设备身份会话的权限范围。
- 自定义后端客户端:已停用的 Control UI 升级输入绝不会向任意后端或 CLI 形式的 WebSocket 客户端授予访问权限。
x-openclaw-scopes过于狭窄:如果代理在 Control UI WebSocket 升级请求中注入此标头,会话权限范围将限制为该标头指定的集合。标头值为空时不会获得任何权限范围。
- 对于 Control UI,请使用 HTTPS,以便浏览器生成设备身份并完成配对。
- 对于自定义自动化,请使用设备身份/配对、预留的直接本地
gateway-client后端辅助程序路径,或管理员 HTTP RPC。 - 不要将已停用的
gateway.controlUi.dangerouslyDisableDeviceAuth键添加到当前配置。旧版安装会自动使用一次性自配对迁移。
WebSocket 仍然失败
WebSocket 仍然失败
请确保代理:
- 支持 WebSocket 升级(
Upgrade: websocket、Connection: upgrade)。 - 在 WebSocket 升级请求中传递身份标头(而不仅是 HTTP 请求)。
- 未对 WebSocket 连接使用单独的身份验证路径。
从令牌身份验证迁移
1
配置代理
配置代理以验证用户身份并传递标头。
2
独立测试代理
独立测试代理设置(使用带标头的 curl)。
3
更新 OpenClaw 配置
更新 OpenClaw 配置以使用可信代理身份验证。
4
重启 Gateway 网关
重启 Gateway 网关。
5
测试 WebSocket
从 Control UI 测试 WebSocket 连接。
6
审计
运行
openclaw security audit 并审查发现的问题。