14>14>
15> 在选择网关的运行位置之前,请先选择网关的地址。通常这是一个私有地址,用户可以在内部网络上或通过 VPN 访问。如果您的内部网络使用公共 IPv4 地址段,您可以列出一个同时包含网关和用户机器的地址段。Claude Code 会将该匹配视为网关位于您内部网络上的标志。请参阅 [为网关选择地址](#choose-an-address-for-the-gateway)。如果以上两种方式都不适合您的网络,请联系您的 Anthropic 客户团队。15> 在选择网关的运行位置之前,请先选择网关的地址。通常这是一个私有地址,用户可以在内部网络上或通过 VPN 访问。如果您的内部网络使用公共 IPv4 地址段,您可以列出一个同时包含网关和用户机器的地址段。Claude Code 会将该匹配视为网关位于您内部网络上的标志。请参阅 [为网关选择地址](#choose-an-address-for-the-gateway)。如果以上两种方式都不适合您的网络,请联系您的 Anthropic 客户团队。
16 16
17本页面涵盖运行 [Claude 应用网关](/docs/zh-CN/claude-apps-gateway) 的运维方面:在身份提供商 (IdP) 中注册 OAuth 客户端、将网关部署为容器,以及日常运行。关于网关在启动时读取的 `gateway.yaml` 文件中的每个选项,请参阅 [配置参考](/docs/zh-CN/claude-apps-gateway-config.md)。17本页面涵盖运行 [Claude 应用网关](https://code.claude.com/docs/zh-CN/claude-apps-gateway) 的运维方面:在身份提供商 (IdP) 中注册 OAuth 客户端、将网关部署为容器,以及日常运行。关于网关在启动时读取的 `gateway.yaml` 文件中的每个选项,请参阅 [配置参考](https://code.claude.com/docs/zh-CN/claude-apps-gateway-config.md)。
18 18
19生产部署按顺序遵循四个步骤,下面的部分与之相对应。前两个是您做出选择的地方;后两个是在运行后参考的材料。19生产部署按顺序遵循四个步骤,下面的部分与之相对应。前两个是您做出选择的地方;后两个是在运行后参考的材料。
20 20
27 27
28## 身份提供商设置28## 身份提供商设置
29 29
30向身份提供商注册一个机密 OAuth/OpenID Connect (OIDC) Web 应用程序,使用单个重定向 URI `https://<gateway>/oauth/callback`,并将其分配给应该有网关访问权限的用户或组。网关使用该注册的客户端密钥向 IdP 进行身份验证;如果您的 IdP 改用[证书凭据](/docs/zh-CN/claude-apps-gateway-config.md#certificate-client-authentication),则使用您上传到该注册的证书进行身份验证。30向身份提供商注册一个机密 OAuth/OpenID Connect (OIDC) Web 应用程序,使用单个重定向 URI `https://<gateway>/oauth/callback`,并将其分配给应该有网关访问权限的用户或组。网关使用该注册的客户端密钥向 IdP 进行身份验证;如果您的 IdP 改用[证书凭据](https://code.claude.com/docs/zh-CN/claude-apps-gateway-config.md#certificate-client-authentication),则使用您上传到该注册的证书进行身份验证。
31 31
32任何符合 OIDC 的 IdP 都可以工作:Okta、Microsoft Entra ID、Google Workspace、Keycloak、Dex、PingFederate 等。IdP 必须满足三个要求:32任何符合 OIDC 的 IdP 都可以工作:Okta、Microsoft Entra ID、Google Workspace、Keycloak、Dex、PingFederate 等。IdP 必须满足三个要求:
33 33
34* 在生产环境中通过 HTTPS 提供 `/.well-known/openid-configuration`;网关接受 [`http://` 发行者](/docs/zh-CN/claude-apps-gateway-config#oidc),本地环回发行者另外需要 `CLAUDE_GATEWAY_ALLOW_LOOPBACK=1`34* 在生产环境中通过 HTTPS 提供 `/.well-known/openid-configuration`;网关接受 [`http://` 发行者](https://code.claude.com/docs/zh-CN/claude-apps-gateway-config#oidc),本地环回发行者另外需要 `CLAUDE_GATEWAY_ALLOW_LOOPBACK=1`
35* 支持授权代码流。PKCE(代码交换证明密钥)默认启用;对于不支持它的 IdP,使用 `oidc.use_pkce: false` 禁用它35* 支持授权代码流。PKCE(代码交换证明密钥)默认启用;对于不支持它的 IdP,使用 `oidc.use_pkce: false` 禁用它
36* 在 id\_token 中返回 `email` 和可选的 `groups`,或使用 `oidc.userinfo_fallback: true` 从 userinfo 端点提供它们36* 在 id\_token 中返回 `email` 和可选的 `groups`,或使用 `oidc.userinfo_fallback: true` 从 userinfo 端点提供它们
37 37
41 41
42* **Okta**:位于 `https://example.okta.com` 的组织授权服务器返回一个省略 `email` 和 `groups` 的简化 id\_token,因此当您将其用作 `issuer` 时设置 `oidc.userinfo_fallback: true`。包含 id\_token 中 `email` 和可选 `groups` 的自定义授权服务器(如 `https://example.okta.com/oauth2/default`)直接发出它们,不需要回退。Okta 仅在 `oidc.scopes` 中请求 `groups` 作用域且应用的组声明过滤器允许时才发出 `groups`;`userinfo_fallback` 无法填充 IdP 未被要求的声明。42* **Okta**:位于 `https://example.okta.com` 的组织授权服务器返回一个省略 `email` 和 `groups` 的简化 id\_token,因此当您将其用作 `issuer` 时设置 `oidc.userinfo_fallback: true`。包含 id\_token 中 `email` 和可选 `groups` 的自定义授权服务器(如 `https://example.okta.com/oauth2/default`)直接发出它们,不需要回退。Okta 仅在 `oidc.scopes` 中请求 `groups` 作用域且应用的组声明过滤器允许时才发出 `groups`;`userinfo_fallback` 无法填充 IdP 未被要求的声明。
43* **Microsoft Entra ID**:`issuer` = `https://login.microsoftonline.com/<tenant-id>/v2.0`。Entra 发出组对象 ID 而不是名称,因此在 `managed.policies.match.groups` 中使用 GUID,或使用应用角色获得人类可读的名称。如果您的租户在 `roles` 而不是 `groups` 下发出角色,设置 `oidc.groups_claim: roles`。43* **Microsoft Entra ID**:`issuer` = `https://login.microsoftonline.com/<tenant-id>/v2.0`。Entra 发出组对象 ID 而不是名称,因此在 `managed.policies.match.groups` 中使用 GUID,或使用应用角色获得人类可读的名称。如果您的租户在 `roles` 而不是 `groups` 下发出角色,设置 `oidc.groups_claim: roles`。
44* **Google Workspace**:`issuer` = `https://accounts.google.com`。Google 的 id\_token 不包含组。要在 Google 作为 IdP 时使用基于组的 `allowed_groups` 或 `managed.policies`,配置 [`oidc.google_groups`](/docs/zh-CN/claude-apps-gateway-config#oidc),它使用具有域范围委派的服务账户通过 Admin SDK Directory API 查找每个用户的组。没有它,使用 `oidc.allowed_email_domains` 进行成员资格门控,使用 `managed.policies.match.email_domain` 进行策略分配。Google 也忽略标准 `offline_access` 作用域。对于刷新令牌,设置 `oidc.scopes: [openid, profile, email]` 和 `oidc.extra_auth_params: { access_type: offline, prompt: consent }`。44* **Google Workspace**:`issuer` = `https://accounts.google.com`。Google 的 id\_token 不包含组。要在 Google 作为 IdP 时使用基于组的 `allowed_groups` 或 `managed.policies`,配置 [`oidc.google_groups`](https://code.claude.com/docs/zh-CN/claude-apps-gateway-config#oidc),它使用具有域范围委派的服务账户通过 Admin SDK Directory API 查找每个用户的组。没有它,使用 `oidc.allowed_email_domains` 进行成员资格门控,使用 `managed.policies.match.email_domain` 进行策略分配。Google 也忽略标准 `offline_access` 作用域。对于刷新令牌,设置 `oidc.scopes: [openid, profile, email]` 和 `oidc.extra_auth_params: { access_type: offline, prompt: consent }`。
45 45
46> [!WARNING]46> [!WARNING]
47>47>
48> 刷新令牌让网关可以在不将开发者发送回浏览器的情况下无声地续订开发者的会话。它们也驱动取消配置,因为当 IdP 禁用用户时,下一次刷新失败,会话在 `ttl_hours` 内结束。网关默认请求 `offline_access` 以获取刷新令牌。如果您的 IdP 需要明确同意离线访问,配置 OAuth 客户端以允许它。48> 刷新令牌让网关可以在不将开发者发送回浏览器的情况下无声地续订开发者的会话。它们也驱动取消配置,因为当 IdP 禁用用户时,下一次刷新失败,会话在 `ttl_hours` 内结束。网关默认请求 `offline_access` 以获取刷新令牌。如果您的 IdP 需要明确同意离线访问,配置 OAuth 客户端以允许它。
49>49>
50> 如果您的 IdP 根本无法发出刷新令牌,网关仍然可以工作,但没有无声续订,因此开发者在会话过期时重新运行浏览器登录。为了防止每小时都发生这种情况,将 [`session.ttl_hours`](/docs/zh-CN/claude-apps-gateway-config#session) 提高到 `8` 或 `12`。权衡是取消配置延迟,因为没有刷新令牌,禁用的用户在更长的 TTL 过期之前保持访问权限。50> 如果您的 IdP 根本无法发出刷新令牌,网关仍然可以工作,但没有无声续订,因此开发者在会话过期时重新运行浏览器登录。为了防止每小时都发生这种情况,将 [`session.ttl_hours`](https://code.claude.com/docs/zh-CN/claude-apps-gateway-config#session) 提高到 `8` 或 `12`。权衡是取消配置延迟,因为没有刷新令牌,禁用的用户在更长的 TTL 过期之前保持访问权限。
51 51
52## 部署52## 部署
53 53
56除了运行位置外,还有一些决策塑造部署:56除了运行位置外,还有一些决策塑造部署:
57 57
58* **成本**:没有单独的许可证或按座位费用。网关是 `claude` 二进制文件的一部分,因此您通过现有承诺为推理付费,加上它运行的计算。58* **成本**:没有单独的许可证或按座位费用。网关是 `claude` 二进制文件的一部分,因此您通过现有承诺为推理付费,加上它运行的计算。
59* **绕过**:网关不强制执行通过它的唯一模型路由。具有自己凭证的开发者仍然可以直接调用提供商,因此关闭该路径是网络策略决策,例如阻止到 `api.anthropic.com` 的出口,除了来自网关的。阻止该出口也会破坏 [WebFetch 域安全检查](/docs/zh-CN/data-usage.md#webfetch-domain-safety-check),它从每个开发者的机器调用 `api.anthropic.com`。在托管策略中设置 `skipWebFetchPreflight: true` 以禁用它。59* **绕过**:网关不强制执行通过它的唯一模型路由。具有自己凭证的开发者仍然可以直接调用提供商,因此关闭该路径是网络策略决策,例如阻止到 `api.anthropic.com` 的出口,除了来自网关的。阻止该出口也会破坏 [WebFetch 域安全检查](https://code.claude.com/docs/zh-CN/data-usage.md#webfetch-domain-safety-check),它从每个开发者的机器调用 `api.anthropic.com`。在托管策略中设置 `skipWebFetchPreflight: true` 以禁用它。
60* **多个网关**:每个是一个单独的部署,有自己的配置,CLI 按网关主机名存储信任和凭证,因此团队可以使用不同的网关而不会冲突。要提供多个 OIDC 发行者,运行单独的实例。60* **多个网关**:每个是一个单独的部署,有自己的配置,CLI 按网关主机名存储信任和凭证,因此团队可以使用不同的网关而不会冲突。要提供多个 OIDC 发行者,运行单独的实例。
61* **无服务器**:Cloud Run 可以工作,如果您设置 `min-instances: 1` 以避免冷 OIDC 发现。Lambda 和 Cloud Functions 不行,因为网关是一个长时间运行的 HTTP 服务器。61* **无服务器**:Cloud Run 可以工作,如果您设置 `min-instances: 1` 以避免冷 OIDC 发现。Lambda 和 Cloud Functions 不行,因为网关是一个长时间运行的 HTTP 服务器。
62 62
63这里的每个生产拓扑都在普通 HTTP 副本前面放置一个 L7 代理,如 Ingress、Cloud Run 的前端或 ALB。设置 [`listen.trusted_proxies`](/docs/zh-CN/claude-apps-gateway-config#listen) 为代理的源范围,以便网关从 `X-Forwarded-For` 读取客户端 IP。网关仅在 TCP 对等体受信任时才遵守该标头。[Google Cloud](/docs/zh-CN/claude-apps-gateway-on-gcp.md) 和 [AWS](/docs/zh-CN/claude-apps-gateway-on-aws.md) 工作示例为每个拓扑提供具体值。没有受信任的代理,每个请求似乎都来自代理的 IP,这会将按 IP 速率限制折叠为一个共享桶,并在审计事件中记录代理的 IP。63这里的每个生产拓扑都在普通 HTTP 副本前面放置一个 L7 代理,如 Ingress、Cloud Run 的前端或 ALB。设置 [`listen.trusted_proxies`](https://code.claude.com/docs/zh-CN/claude-apps-gateway-config#listen) 为代理的源范围,以便网关从 `X-Forwarded-For` 读取客户端 IP。网关仅在 TCP 对等体受信任时才遵守该标头。[Google Cloud](https://code.claude.com/docs/zh-CN/claude-apps-gateway-on-gcp.md) 和 [AWS](https://code.claude.com/docs/zh-CN/claude-apps-gateway-on-aws.md) 工作示例为每个拓扑提供具体值。没有受信任的代理,每个请求似乎都来自代理的 IP,这会将按 IP 速率限制折叠为一个共享桶,并在审计事件中记录代理的 IP。
64 64
65不要在网关的设备授权和令牌端点处重定向请求,例如在入口处使用 HTTP 到 HTTPS 或主机规范化重写。Claude Code 不会在这些请求上跟随重定向,因此会破坏登录和令牌刷新的入口规则。65不要在网关的设备授权和令牌端点处重定向请求,例如在入口处使用 HTTP 到 HTTPS 或主机规范化重写。Claude Code 不会在这些请求上跟随重定向,因此会破坏登录和令牌刷新的入口规则。
66 66
69* 在除 `provider: anthropic` 之外的每个上游上,一旦流已经沉默约 15 秒,网关就会写入一个 SSE `ping`。69* 在除 `provider: anthropic` 之外的每个上游上,一旦流已经沉默约 15 秒,网关就会写入一个 SSE `ping`。
70* 在 `provider: anthropic` 上,网关原样传递响应,包括 Anthropic API 自己的 ping。70* 在 `provider: anthropic` 上,网关原样传递响应,包括 Anthropic API 自己的 ping。
71 71
72默认值(如 ALB 的 60 秒)足以保持安静的流打开。[AWS 工作示例](/docs/zh-CN/claude-apps-gateway-on-aws.md#troubleshooting) 无论如何将其提高到一小时,其故障排除行涵盖早于 v2.1.229 的网关,这些网关在现在获得 ping 的上游上的安静期间没有发送任何内容。72默认值(如 ALB 的 60 秒)足以保持安静的流打开。[AWS 工作示例](https://code.claude.com/docs/zh-CN/claude-apps-gateway-on-aws.md#troubleshooting) 无论如何将其提高到一小时,其故障排除行涵盖早于 v2.1.229 的网关,这些网关在现在获得 ping 的上游上的安静期间没有发送任何内容。
73 73
74### 为网关选择地址74### 为网关选择地址
75 75
76Claude Code 通过以下两种方式之一接受网关的地址:76Claude Code 通过以下两种方式之一接受网关的地址:
77 77
78* **私有地址**:将网关置于内部负载均衡器或 VPN 之后,并使用仅解析为私有地址(如 RFC 1918 或 CGNAT `100.64.0.0/10`)的主机名。用户的机器可以使用任何地址。[私有网络前提条件](/docs/zh-CN/claude-apps-gateway#prerequisites) 列出了可接受的地址范围。78* **私有地址**:将网关置于内部负载均衡器或 VPN 之后,并使用仅解析为私有地址(如 RFC 1918 或 CGNAT `100.64.0.0/10`)的主机名。用户的机器可以使用任何地址。[私有网络前提条件](https://code.claude.com/docs/zh-CN/claude-apps-gateway#prerequisites) 列出了可接受的地址范围。
79* **声明的地址块**:如果您的内部网络使用贵组织拥有的公共 IPv4 地址空间,请在 `gatewayInternalNetworks` 托管设置中列出该地址块。网关和用户的机器都必须位于该地址块内。请参阅 [允许网关使用您拥有的公共地址空间](/docs/zh-CN/claude-apps-gateway#allow-a-gateway-on-public-address-space-you-own)。79* **声明的地址块**:如果您的内部网络使用贵组织拥有的公共 IPv4 地址空间,请在 `gatewayInternalNetworks` 托管设置中列出该地址块。网关和用户的机器都必须位于该地址块内。请参阅 [允许网关使用您拥有的公共地址空间](https://code.claude.com/docs/zh-CN/claude-apps-gateway#allow-a-gateway-on-public-address-space-you-own)。
80 80
81如果没有单个地址块能同时包含两者,请改为给网关分配私有地址。81如果没有单个地址块能同时包含两者,请改为给网关分配私有地址。
82 82
84 84
85围绕标准 Claude Code 版本中的本机 `claude` 二进制文件构建您自己的镜像:85围绕标准 Claude Code 版本中的本机 `claude` 二进制文件构建您自己的镜像:
86 86
871. 从固定版本下载您的镜像架构的 Linux 构建;请参阅 [安装特定版本](/docs/zh-CN/setup.md#install-a-specific-version) 了解下载 URL。871. 从固定版本下载您的镜像架构的 Linux 构建;请参阅 [安装特定版本](https://code.claude.com/docs/zh-CN/setup.md#install-a-specific-version) 了解下载 URL。
882. 根据版本的 GPG 签名 `manifest.json` 验证它,如 [二进制完整性和代码签名](/docs/zh-CN/setup.md#binary-integrity-and-code-signing) 中所述。882. 根据版本的 GPG 签名 `manifest.json` 验证它,如 [二进制完整性和代码签名](https://code.claude.com/docs/zh-CN/setup.md#binary-integrity-and-code-signing) 中所述。
893. 将其复制到构建上下文中。893. 将其复制到构建上下文中。
90 90
91如果您的构建无法到达版本主机,请将版本镜像到您的内部注册表中,并固定您的舰队运行的版本。91如果您的构建无法到达版本主机,请将版本镜像到您的内部注册表中,并固定您的舰队运行的版本。
92 92
93除了二进制文件外,镜像还需要:93除了二进制文件外,镜像还需要:
94 94
95* **基于 glibc 的镜像**:glibc 构建的唯一动态依赖项是 glibc 库。基于 Musl 的镜像需要 `linux-x64-musl` 或 `linux-arm64-musl` 构建加上额外的包;请参阅 [Alpine Linux 设置](/docs/zh-CN/setup.md#alpine-linux-and-musl-based-distributions)。95* **基于 glibc 的镜像**:glibc 构建的唯一动态依赖项是 glibc 库。基于 Musl 的镜像需要 `linux-x64-musl` 或 `linux-arm64-musl` 构建加上额外的包;请参阅 [Alpine Linux 设置](https://code.claude.com/docs/zh-CN/setup.md#alpine-linux-and-musl-based-distributions)。
96* **可写状态目录**:网关以任何用户身份运行,但最小镜像没有可写的主目录。将 `CLAUDE_CONFIG_DIR` 设置为可写路径,如 `/tmp/.claude`。96* **可写状态目录**:网关以任何用户身份运行,但最小镜像没有可写的主目录。将 `CLAUDE_CONFIG_DIR` 设置为可写路径,如 `/tmp/.claude`。
97* **容器命令**:`claude gateway --config /etc/claude/gateway.yaml`,配置文件以只读方式挂载,密钥作为环境变量提供;网关在 `listen.port` 上监听,默认为 `8080`。97* **容器命令**:`claude gateway --config /etc/claude/gateway.yaml`,配置文件以只读方式挂载,密钥作为环境变量提供;网关在 `listen.port` 上监听,默认为 `8080`。
98 98
104* 在 Ingress 处终止 TLS 并将 `listen.public_url` 设置为 Ingress 主机名104* 在 Ingress 处终止 TLS 并将 `listen.public_url` 设置为 Ingress 主机名
105* 将就绪探针指向 `GET /readyz`,将活跃探针指向 `GET /healthz`105* 将就绪探针指向 `GET /readyz`,将活跃探针指向 `GET /healthz`
106 106
107有关 AWS 上的完整工作示例,涵盖 ECS Fargate 或 EKS、Amazon RDS 和 AWS Secrets Manager,请参阅 [在 AWS 上部署](/docs/zh-CN/claude-apps-gateway-on-aws.md)。107有关 AWS 上的完整工作示例,涵盖 ECS Fargate 或 EKS、Amazon RDS 和 AWS Secrets Manager,请参阅 [在 AWS 上部署](https://code.claude.com/docs/zh-CN/claude-apps-gateway-on-aws.md)。
108 108
109优先使用平台的工作负载身份而不是静态密钥;[`upstreams` 参考](/docs/zh-CN/claude-apps-gateway-config#upstreams) 有每个平台的设置详情。对于跨云配对,如 GKE 上的 Amazon Bedrock 上游,在上游的 `auth` 块中设置显式凭证。109优先使用平台的工作负载身份而不是静态密钥;[`upstreams` 参考](https://code.claude.com/docs/zh-CN/claude-apps-gateway-config#upstreams) 有每个平台的设置详情。对于跨云配对,如 GKE 上的 Amazon Bedrock 上游,在上游的 `auth` 块中设置显式凭证。
110 110
111### Cloud Run111### Cloud Run
112 112
113按如下方式配置服务:113按如下方式配置服务:
114 114
115* 将 `listen.port` 保留在其默认值 `8080`,这与 Cloud Run 的默认 `PORT` 匹配,或设置 `port: ${PORT}`115* 将 `listen.port` 保留在其默认值 `8080`,这与 Cloud Run 的默认 `PORT` 匹配,或设置 `port: ${PORT}`
116* 将 `public_url` 设置为外部可达的源。对于生产,这通常是内部负载均衡器的主机名,因为 `/login` [拒绝公共地址](/docs/zh-CN/claude-apps-gateway#prerequisites),而 `*.run.app` URL 解析为一个,所以单独的 Cloud Run URL 仅适用于 `curl` 或浏览器烟雾测试。例外是一个网络,其中 `*.run.app` 通过 Private Service Connect 和 Cloud DNS 私有区域私下解析;在该拓扑中,Cloud Run URL 是有效的 `public_url`。[Google Cloud 工作示例](/docs/zh-CN/claude-apps-gateway-on-gcp.md#deploy-the-gateway) 涵盖两者。116* 将 `public_url` 设置为外部可达的源。对于生产,这通常是内部负载均衡器的主机名,因为 `/login` [拒绝公共地址](https://code.claude.com/docs/zh-CN/claude-apps-gateway#prerequisites),而 `*.run.app` URL 解析为一个,所以单独的 Cloud Run URL 仅适用于 `curl` 或浏览器烟雾测试。例外是一个网络,其中 `*.run.app` 通过 Private Service Connect 和 Cloud DNS 私有区域私下解析;在该拓扑中,Cloud Run URL 是有效的 `public_url`。[Google Cloud 工作示例](https://code.claude.com/docs/zh-CN/claude-apps-gateway-on-gcp.md#deploy-the-gateway) 涵盖两者。
117* 将配置作为密钥卷挂载117* 将配置作为密钥卷挂载
118* 设置 `min-instances: 1` 以避免首次请求时的冷 OIDC 发现118* 设置 `min-instances: 1` 以避免首次请求时的冷 OIDC 发现
119 119
120有关 Google Cloud 上的完整工作示例,涵盖 Cloud Run 或 GKE、Cloud SQL 和 Secret Manager,请参阅 [在 Google Cloud 上部署](/docs/zh-CN/claude-apps-gateway-on-gcp.md)。120有关 Google Cloud 上的完整工作示例,涵盖 Cloud Run 或 GKE、Cloud SQL 和 Secret Manager,请参阅 [在 Google Cloud 上部署](https://code.claude.com/docs/zh-CN/claude-apps-gateway-on-gcp.md)。
121 121
122### 将网关 URL 推送到开发者机器122### 将网关 URL 推送到开发者机器
123 123
124一旦网关开始提供服务,通过托管设置、MDM 或直接写入每个操作系统的 `managed-settings.json` 将 `forceLoginMethod`、`forceLoginGatewayUrl` 和 `parentSettingsBehavior: "merge"` 推送到每个开发者的机器。124一旦网关开始提供服务,通过托管设置、MDM 或直接写入每个操作系统的 `managed-settings.json` 将 `forceLoginMethod`、`forceLoginGatewayUrl` 和 `parentSettingsBehavior: "merge"` 推送到每个开发者的机器。
125 125
126一旦您部署密钥,Claude Code 停止使用机器上剩余的 API 密钥或 claude.ai 登录,因此计划与您的登录说明一起推送。[管理员策略需要 Cloud 网关登录](/docs/zh-CN/errors.md#administrator-policy-requires-a-cloud-gateway-sign-in) 描述开发者看到的消息。126一旦您部署密钥,Claude Code 停止使用机器上剩余的 API 密钥或 claude.ai 登录,因此计划与您的登录说明一起推送。[管理员策略需要 Cloud 网关登录](https://code.claude.com/docs/zh-CN/errors.md#administrator-policy-requires-a-cloud-gateway-sign-in) 描述开发者看到的消息。
127 127
128请参阅 [每个机制存储策略的位置](/docs/zh-CN/managed-settings.md#where-each-mechanism-stores-the-policy) 了解文件路径,以及 [客户端托管设置](/docs/zh-CN/claude-apps-gateway-config.md#client-side-managed-settings) 了解 Claude Desktop `bootstrapUrl` 等效项。128请参阅 [每个机制存储策略的位置](https://code.claude.com/docs/zh-CN/managed-settings.md#where-each-mechanism-stores-the-policy) 了解文件路径,以及 [客户端托管设置](https://code.claude.com/docs/zh-CN/claude-apps-gateway-config.md#client-side-managed-settings) 了解 Claude Desktop `bootstrapUrl` 等效项。
129 129
130### 大规模推出130### 大规模推出
131 131
132登录按客户端 IP 地址进行速率限制,默认值适合小团队。每个地址每 10 分钟获得 30 次登录开始和 10 次代码提交。向数千名开发者的推出可能在第一个早上达到这些限制,原因有两个:132登录按客户端 IP 地址进行速率限制,默认值适合小团队。每个地址每 10 分钟获得 30 次登录开始和 10 次代码提交。向数千名开发者的推出可能在第一个早上达到这些限制,原因有两个:
133 133
134* **网关看不到您的负载均衡器后面。** 没有 [`listen.trusted_proxies`](/docs/zh-CN/claude-apps-gateway-config#listen),每个开发者似乎都来自负载均衡器的地址并共享一个限制。首先设置它。网关在第一次忽略 `X-Forwarded-For` 标头时会记录警告。134* **网关看不到您的负载均衡器后面。** 没有 [`listen.trusted_proxies`](https://code.claude.com/docs/zh-CN/claude-apps-gateway-config#listen),每个开发者似乎都来自负载均衡器的地址并共享一个限制。首先设置它。网关在第一次忽略 `X-Forwarded-For` 标头时会记录警告。
135* **许多开发者共享几个 NAT 或 VPN 出口地址。** 即使 `trusted_proxies` 正确,他们也共享这些地址的限制。提高 [`rate_limits`](/docs/zh-CN/claude-apps-gateway-config#http-tuning) 以适应。135* **许多开发者共享几个 NAT 或 VPN 出口地址。** 即使 `trusted_proxies` 正确,他们也共享这些地址的限制。提高 [`rate_limits`](https://code.claude.com/docs/zh-CN/claude-apps-gateway-config#http-tuning) 以适应。
136 136
137要调整 `max`,将开发者数除以他们共享的出口地址数。估计在一个 `window_seconds` 周期内有多少人登录,默认为 10 分钟。然后将其加倍以覆盖重试和同时登录 Claude Code 和 Claude Desktop 的开发者。137要调整 `max`,将开发者数除以他们共享的出口地址数。估计在一个 `window_seconds` 周期内有多少人登录,默认为 10 分钟。然后将其加倍以覆盖重试和同时登录 Claude Code 和 Claude Desktop 的开发者。
138 138
146 146
147`device_verify` 是阻止某人猜测另一个开发者登录代码的原因,因此仅在您的估计需要的范围内提高它。即使在这些限制下,代码也是来自 20 字符字母表的 8 个字符,并在 10 分钟后过期,因此猜测仍然不切实际;请参阅 [用户代码暴力破解抵抗](#user-code-brute-force-resistance)。147`device_verify` 是阻止某人猜测另一个开发者登录代码的原因,因此仅在您的估计需要的范围内提高它。即使在这些限制下,代码也是来自 20 字符字母表的 8 个字符,并在 10 分钟后过期,因此猜测仍然不切实际;请参阅 [用户代码暴力破解抵抗](#user-code-brute-force-resistance)。
148 148
149当您的 IdP 发出刷新令牌时,Claude Code 会无声地续订会话,因此您可以在推出后将限制放回。没有刷新令牌,开发者每 [`session.ttl_hours`](/docs/zh-CN/claude-apps-gateway-config#session) 再次登录。为该稳定速率调整两个限制的大小,并保持它们提高。149当您的 IdP 发出刷新令牌时,Claude Code 会无声地续订会话,因此您可以在推出后将限制放回。没有刷新令牌,开发者每 [`session.ttl_hours`](https://code.claude.com/docs/zh-CN/claude-apps-gateway-config#session) 再次登录。为该稳定速率调整两个限制的大小,并保持它们提高。
150 150
151当达到限制时,Claude Code v2.1.274 或更高版本显示 `The gateway is limiting sign-in attempts right now`。v2.1.274 或更高版本的网关在验证页面上显示 `Too many attempts came from your network address`,并提供要检查的设置。它还写入一条 `sign-in refused` 日志行,命名要更改的设置。151当达到限制时,Claude Code v2.1.274 或更高版本显示 `The gateway is limiting sign-in attempts right now`。v2.1.274 或更高版本的网关在验证页面上显示 `Too many attempts came from your network address`,并提供要检查的设置。它还写入一条 `sign-in refused` 日志行,命名要更改的设置。
152 152
166 * `auth.denied` 和 `access.denied` 携带原因和客户端 IP,加上 `auth.denied` 的请求路径,因为在这些拒绝时不存在用户身份。两个 `access.denied` 原因改变事件携带的内容:166 * `auth.denied` 和 `access.denied` 携带原因和客户端 IP,加上 `auth.denied` 的请求路径,因为在这些拒绝时不存在用户身份。两个 `access.denied` 原因改变事件携带的内容:
167 * `xff_unparseable`:事件也携带无法读取的 `X-Forwarded-For` 条目167 * `xff_unparseable`:事件也携带无法读取的 `X-Forwarded-For` 条目
168 * `client_ip_unknown`:事件不携带客户端 IP,因为连接没有对等地址,而设置了 `access_control` 列表168 * `client_ip_unknown`:事件不携带客户端 IP,因为连接没有对等地址,而设置了 `access_control` 列表
169 * `access.public_client` 携带每个进程从公共地址到达的第一个请求的客户端 IP,而 `access_control.allow_cidrs` 为空。网关照常提供请求;该事件表示网关可能可从公共互联网访问。请参阅 [`access_control` 参考](/docs/zh-CN/claude-apps-gateway-config#http-tuning) 了解什么被视为公共以及推荐的允许列表。169 * `access.public_client` 携带每个进程从公共地址到达的第一个请求的客户端 IP,而 `access_control.allow_cidrs` 为空。网关照常提供请求;该事件表示网关可能可从公共互联网访问。请参阅 [`access_control` 参考](https://code.claude.com/docs/zh-CN/claude-apps-gateway-config#http-tuning) 了解什么被视为公共以及推荐的允许列表。
170 * `inference` 记录哪个上游提供了请求以及响应状态170 * `inference` 记录哪个上游提供了请求以及响应状态
171 * `desktop_bootstrap.denied` 记录被拒绝的 Claude Desktop bootstrap 获取,包含原因(`not_configured`、`policy_not_opted_in` 或 `no_policy_matched`)和用户的身份171 * `desktop_bootstrap.denied` 记录被拒绝的 Claude Desktop bootstrap 获取,包含原因(`not_configured`、`policy_not_opted_in` 或 `no_policy_matched`)和用户的身份
172 * `admin.denied` 记录被拒绝的管理员 API 身份验证尝试,包括客户端 IP、方法、路径和原因,不包括呈现的密钥材料:当呈现了 `x-api-key` 但与配置的密钥不匹配时为 `invalid_key`,当仅呈现了 `Authorization` 标头且其未验证为 `admin.admin_groups` 中的网关会话时为 `bearer_rejected`,或当两个标头都未呈现时为 `no_credentials`172 * `admin.denied` 记录被拒绝的管理员 API 身份验证尝试,包括客户端 IP、方法、路径和原因,不包括呈现的密钥材料:当呈现了 `x-api-key` 但与配置的密钥不匹配时为 `invalid_key`,当仅呈现了 `Authorization` 标头且其未验证为 `admin.admin_groups` 中的网关会话时为 `bearer_rejected`,或当两个标头都未呈现时为 `no_credentials`
174 174
175### 健康175### 健康
176 176
177网关提供 `GET /healthz` 作为活跃探针和 `GET /readyz` 作为就绪探针。`/readyz` 验证存储是否可达。如果您设置了 [`store.readiness_grace_seconds`](/docs/zh-CN/claude-apps-gateway-config#store),`/readyz` 在存储停止应答后最多继续报告就绪达到那么多秒。177网关提供 `GET /healthz` 作为活跃探针和 `GET /readyz` 作为就绪探针。`/readyz` 验证存储是否可达。如果您设置了 [`store.readiness_grace_seconds`](https://code.claude.com/docs/zh-CN/claude-apps-gateway-config#store),`/readyz` 在存储停止应答后最多继续报告就绪达到那么多秒。
178 178
179两个端点都免除 `access_control.allow_cidrs`,因此探针在锁定的监听器上继续工作。179两个端点都免除 `access_control.allow_cidrs`,因此探针在锁定的监听器上继续工作。
180 180
184 184
185默认情况下,每个网关副本最多同时向上游发送 256 个请求。流式响应在流结束前计入限制。185默认情况下,每个网关副本最多同时向上游发送 256 个请求。流式响应在流结束前计入限制。
186 186
187当副本达到限制时到达的请求在网关内等待一个空闲槽位。开发者看到一个响应缓慢启动或似乎挂起。在 `provider: anthropic` 上游上,等待时间超过 [`timeouts.upstream_ttfb_ms`](/docs/zh-CN/claude-apps-gateway-config#http-tuning) 的请求放弃该上游,当没有后续上游提供它时以 502 失败。187当副本达到限制时到达的请求在网关内等待一个空闲槽位。开发者看到一个响应缓慢启动或似乎挂起。在 `provider: anthropic` 上游上,等待时间超过 [`timeouts.upstream_ttfb_ms`](https://code.claude.com/docs/zh-CN/claude-apps-gateway-config#http-tuning) 的请求放弃该上游,当没有后续上游提供它时以 502 失败。
188 188
189包含 `upstream requests:` 的启动日志行显示生效的限制。当副本的打开请求数超过限制时,它也最多每分钟记录一次包含 `client requests are open` 的警告。189包含 `upstream requests:` 的启动日志行显示生效的限制。当副本的打开请求数超过限制时,它也最多每分钟记录一次包含 `client requests are open` 的警告。
190 190
203 203
204### 使 `API_TIMEOUT_MS` 高于网关的首字节时间204### 使 `API_TIMEOUT_MS` 高于网关的首字节时间
205 205
206如果您降低 [`API_TIMEOUT_MS`](/docs/zh-CN/network-config#streaming-idle-watchdogs) 以便更快地重试未得到应答的请求,请使其高于网关发送流式响应首批字节所需的时间。等待时间更长的请求会超时,同样等待那么久的每次重试也会超时,直到该轮次以 `Request timed out` 结束。206如果您降低 [`API_TIMEOUT_MS`](https://code.claude.com/docs/zh-CN/network-config#streaming-idle-watchdogs) 以便更快地重试未得到应答的请求,请使其高于网关发送流式响应首批字节所需的时间。等待时间更长的请求会超时,同样等待那么久的每次重试也会超时,直到该轮次以 `Request timed out` 结束,除非[首字节截止时间](#retry-an-unanswered-request-sooner-with-the-first-byte-deadline)先将其结束。
207 207
208* **`provider: anthropic`**:将 `API_TIMEOUT_MS` 设置为高于您的上游发送其第一个事件所需的最长时间。208* **`provider: anthropic`**:将 `API_TIMEOUT_MS` 设置为高于您的上游发送其第一个事件所需的最长时间。
209* **其他所有上游**:将其设置为比您的上游返回响应标头所需的最长时间多出 20 秒以上。网关在这些标头之后约 15 秒发送其第一个 [keepalive `ping`](#deployment),除非上游的第一个事件更早到达。早于 v2.1.229 的网关不发送 ping,因此在那里请使用 `provider: anthropic` 规则。209* **其他所有上游**:将其设置为比您的上游返回响应标头所需的最长时间多出 20 秒以上。网关在这些标头之后约 15 秒发送其第一个 [keepalive `ping`](#deployment),除非上游的第一个事件更早到达。早于 v2.1.229 的网关不发送 ping,因此在那里请使用 `provider: anthropic` 规则。
210 210
211在此时间之上,还要考虑任何[等待空闲槽位](#concurrent-upstream-requests)的时间,以及在[故障转移](/docs/zh-CN/claude-apps-gateway-config.md#multiple-upstreams)之前等待已宕机上游的时间。同时也要使该值高于最长的[非流式请求](/docs/zh-CN/network-config.md#streaming-idle-watchdogs)。211在此时间之上,还要考虑任何[等待空闲槽位](#concurrent-upstream-requests)的时间,以及在[故障转移](https://code.claude.com/docs/zh-CN/claude-apps-gateway-config.md#multiple-upstreams)之前等待已宕机上游的时间。同时也要使该值高于最长的[非流式请求](https://code.claude.com/docs/zh-CN/network-config.md#streaming-idle-watchdogs)。
212
213### 使用首字节截止时间更快地重试未得到应答的请求
214
215要让 Claude Code 更快地重试未得到应答的流式请求,请在开发者的机器上设置 [`CLAUDE_STREAM_FIRST_BYTE_TIMEOUT_MS`](https://code.claude.com/docs/zh-CN/env-vars),为其设定首字节截止时间。该截止时间限制首次尝试等待响应标头的时长。没有它,该尝试可能等待 5 到 6 分钟。需要开发者机器上的 Claude Code v2.1.307 或更高版本。
216
217将该变量设置为以毫秒为单位的正整数,可以在[网关策略的 `env` 块](#deliver-the-value-in-a-policy)中或开发者的 shell 中设置。请使该值高于网关最长的[首字节时间](#keep-api_timeout_ms-above-the-gateways-time-to-first-byte),否则 Claude Code 可能会中止并重新发送标头返回较慢的健康请求。此示例在开发者的 shell 中设置 60 秒:
218
219```bash theme={null}
220export CLAUDE_STREAM_FIRST_BYTE_TIMEOUT_MS=60000
221```
222
223未得到应答的重新发送可能等待 5 到 6 分钟,直到[响应体空闲超时](https://code.claude.com/docs/zh-CN/network-config.md#streaming-idle-watchdogs)将其结束,然后 Claude Code 在[重试预算](https://code.claude.com/docs/zh-CN/errors.md#tune-retry-behavior)内重试它。如果您降低 `API_TIMEOUT_MS` 只是为了更快地重试,请移除该值,否则一次未得到应答的重新发送就可能以 [No response from API](https://code.claude.com/docs/zh-CN/errors.md#no-response-from-api) 结束该轮次。
224
225要确认截止时间已触发,请让开发者在启用[调试日志](https://code.claude.com/docs/zh-CN/network-config.md#verify-your-configuration)的情况下启动 Claude Code,然后在日志中搜索 `[first-byte] no response headers`。
212 226
213### 中断行为227### 中断行为
214 228
216 230
217* **现有会话**:持有者令牌使用 JWT 密钥在本地验证,会话刷新不接触存储,网关进程仍然可以提供推理231* **现有会话**:持有者令牌使用 JWT 密钥在本地验证,会话刷新不接触存储,网关进程仍然可以提供推理
218* **新登录**:失败直到 Postgres 恢复,因为设备流及其速率限制计数器存在于 Postgres 中232* **新登录**:失败直到 Postgres 恢复,因为设备流及其速率限制计数器存在于 Postgres 中
219* **[支出限制执行](/docs/zh-CN/claude-apps-gateway-spend-limits.md#postgres-availability)**:在中断期间默认失败开放,因此推理仍然流动;如果您宁愿阻止而不是无计量运行,将其翻转为失败关闭233* **[支出限制执行](https://code.claude.com/docs/zh-CN/claude-apps-gateway-spend-limits.md#postgres-availability)**:在中断期间默认失败开放,因此推理仍然流动;如果您宁愿阻止而不是无计量运行,将其翻转为失败关闭
220* **就绪**:默认情况下,`/readyz` 在 Postgres 无法访问时立即报告未就绪,因此每个副本一次失败其就绪检查。在流量仅到达通过检查的副本的地方,所有流量,包括网关仍然可以提供的推理,在 Postgres 恢复前失败。`/healthz` 上的活跃探针在整个过程中继续通过。234* **就绪**:默认情况下,`/readyz` 在 Postgres 无法访问时立即报告未就绪,因此每个副本一次失败其就绪检查。在流量仅到达通过检查的副本的地方,所有流量,包括网关仍然可以提供的推理,在 Postgres 恢复前失败。`/healthz` 上的活跃探针在整个过程中继续通过。
221 235
222如果您的 IdP 宕机,现有会话工作直到 `ttl_hours`,新登录失败。会话刷新获得重试答案并在 IdP 恢复后成功。如果您的 IdP 有频繁的维护窗口,设置更长的 `ttl_hours`。236如果您的 IdP 宕机,现有会话工作直到 `ttl_hours`,新登录失败。会话刷新获得重试答案并在 IdP 恢复后成功。如果您的 IdP 有频繁的维护窗口,设置更长的 `ttl_hours`。
223 237
224#### 就绪宽限期238#### 就绪宽限期
225 239
226要让已登录的开发者在短 Postgres 中断(如数据库故障转移)期间继续工作,将 [`store.readiness_grace_seconds`](/docs/zh-CN/claude-apps-gateway-config#store) 设置为比故障转移花费的时间更长,例如 `300`。启用支出限制并使用默认失败开放行为,通过保持就绪的副本的请求在 Postgres 恢复前无计量,因此将值保持为低至覆盖您的故障转移。如果您设置了 [`enforcement.fail_closed_on_error: true`](/docs/zh-CN/claude-apps-gateway-config#enforcement),网关拒绝已登录开发者的推理,带有 `429` `spend limit unavailable` 消息,直到 Postgres 恢复,即使副本仍然通过其就绪检查。240要让已登录的开发者在短 Postgres 中断(如数据库故障转移)期间继续工作,将 [`store.readiness_grace_seconds`](https://code.claude.com/docs/zh-CN/claude-apps-gateway-config#store) 设置为比故障转移花费的时间更长,例如 `300`。启用支出限制并使用默认失败开放行为,通过保持就绪的副本的请求在 Postgres 恢复前无计量,因此将值保持为低至覆盖您的故障转移。如果您设置了 [`enforcement.fail_closed_on_error: true`](https://code.claude.com/docs/zh-CN/claude-apps-gateway-config#enforcement),网关拒绝已登录开发者的推理,带有 `429` `spend limit unavailable` 消息,直到 Postgres 恢复,即使副本仍然通过其就绪检查。
227 241
228该设置需要网关服务器上的 Claude Code v2.1.282 或更高版本。较早的网关在找到密钥时拒绝启动,因此在添加它之前升级每个副本。[升级](#upgrades) 涵盖回滚。242该设置需要网关服务器上的 Claude Code v2.1.282 或更高版本。较早的网关在找到密钥时拒绝启动,因此在添加它之前升级每个副本。[升级](#upgrades) 涵盖回滚。
229 243
243 257
244网关将其状态存储在 PostgreSQL 数据库中:258网关将其状态存储在 PostgreSQL 数据库中:
245 259
246* **数据库**:PostgreSQL 本身,自托管或托管均可,版本为[最低版本](/docs/zh-CN/claude-apps-gateway#prerequisites)或更高。仅实现 Postgres 协议的数据库(例如分布式 SQL 数据库)不受支持。260* **数据库**:PostgreSQL 本身,自托管或托管均可,版本为[最低版本](https://code.claude.com/docs/zh-CN/claude-apps-gateway#prerequisites)或更高。仅实现 Postgres 协议的数据库(例如分布式 SQL 数据库)不受支持。
247* **地址**:`store.postgres_url` 接受一个主机。如果数据库有多个节点,请使用位于它们前面的地址,例如您的托管服务的端点、负载均衡器或虚拟 IP。设置一个比故障转移所需时间更长的[就绪宽限期](#readiness-grace-period)。261* **地址**:`store.postgres_url` 接受一个主机。如果数据库有多个节点,请使用位于它们前面的地址,例如您的托管服务的端点、负载均衡器或虚拟 IP。设置一个比故障转移所需时间更长的[就绪宽限期](#readiness-grace-period)。
248 262
249网关持有五个数据表加上一个 `_migrations` 表,全部由其启动时迁移创建:263网关持有五个数据表加上一个 `_migrations` 表,全部由其启动时迁移创建:
256| `admin_audit` | 管理员 API 变更跟踪 | `admin.audit_retention_days`,默认 365 |270| `admin_audit` | 管理员 API 变更跟踪 | `admin.audit_retention_days`,默认 365 |
257| `principal_emails` | 每个主体的最后看到的电子邮件、显示名称和 IdP 组。包含 PII。 | `admin.identity_retention_days` 自上次活动以来,默认 90 |271| `principal_emails` | 每个主体的最后看到的电子邮件、显示名称和 IdP 组。包含 PII。 | `admin.identity_retention_days` 自上次活动以来,默认 90 |
258 272
259一个 30 秒的循环过期 `kv` 行超过其 TTL,一个每小时的扫描在支出表上强制保留窗口,因此没有什么无限增长。没有 [支出限制](/docs/zh-CN/claude-apps-gateway-spend-limits.md) 配置,只有 `kv` 被写入。网关在启动时应用其自己的架构迁移,在每次升级时也是如此,因此其数据库角色需要创建和修改表的权限。将其指向专用于网关的数据库或架构,以保持该授权范围狭窄。273一个 30 秒的循环过期 `kv` 行超过其 TTL,一个每小时的扫描在支出表上强制保留窗口,因此没有什么无限增长。没有 [支出限制](https://code.claude.com/docs/zh-CN/claude-apps-gateway-spend-limits.md) 配置,只有 `kv` 被写入。网关在启动时应用其自己的架构迁移,在每次升级时也是如此,因此其数据库角色需要创建和修改表的权限。将其指向专用于网关的数据库或架构,以保持该授权范围狭窄。
260 274
261使用支出限制,丢失的数据库意味着丢失支出跟踪和上限,不仅仅是开发者重新登录,因此运行定期备份。要立即删除一个离职的开发者而不是等待保留,直接运行 `DELETE FROM principal_emails WHERE principal = '<sub>'`;这移除了唯一持有其电子邮件、名称和组的表。`spend` 和 `admin_audit` 行仅引用伪匿名 OIDC `sub`。275使用支出限制,丢失的数据库意味着丢失支出跟踪和上限,不仅仅是开发者重新登录,因此运行定期备份。要立即删除一个离职的开发者而不是等待保留,直接运行 `DELETE FROM principal_emails WHERE principal = '<sub>'`;这移除了唯一持有其电子邮件、名称和组的表。`spend` 和 `admin_audit` 行仅引用伪匿名 OIDC `sub`。
262 276
263#### 确定连接池大小277#### 确定连接池大小
264 278
265每个副本最多打开 [`store.max_connections`](/docs/zh-CN/claude-apps-gateway-config#store) 个 Postgres 连接,默认为五个。请使副本数 × `store.max_connections` 不超过数据库为网关剩余的连接数:279每个副本最多打开 [`store.max_connections`](https://code.claude.com/docs/zh-CN/claude-apps-gateway-config#store) 个 Postgres 连接,默认为五个。请使副本数 × `store.max_connections` 不超过数据库为网关剩余的连接数:
266 280
267* **副本**:统计同时运行的最大数量。从您的自动扩展最大值开始,如果您不使用自动扩展,则从副本数开始,再加上滚动更新在停止旧副本之前启动的额外副本。在使用默认设置的 Amazon ECS 上以及在 Cloud Run 上,额外副本可能与原数量一样多。281* **副本**:统计同时运行的最大数量。从您的自动扩展最大值开始,如果您不使用自动扩展,则从副本数开始,再加上滚动更新在停止旧副本之前启动的额外副本。在使用默认设置的 Amazon ECS 上以及在 Cloud Run 上,额外副本可能与原数量一样多。
268* **剩余连接**:取数据库的 `max_connections`,然后减去数据库保留的连接以及其他客户端持有的连接。PostgreSQL 保留 `superuser_reserved_connections`,默认为三个。托管服务可能保留更多,因此请查看其文档。282* **剩余连接**:取数据库的 `max_connections`,然后减去数据库保留的连接以及其他客户端持有的连接。PostgreSQL 保留 `superuser_reserved_connections`,默认为三个。托管服务可能保留更多,因此请查看其文档。
273 287
274* **数据库**:提高其 `max_connections`288* **数据库**:提高其 `max_connections`
275* **副本**:运行更少的副本,或让您的编排器在滚动更新中启动更少的额外副本289* **副本**:运行更少的副本,或让您的编排器在滚动更新中启动更少的额外副本
276* **连接池**:降低 `store.max_connections`,但在启用[支出限制](/docs/zh-CN/claude-apps-gateway-spend-limits.md)时,请使其足够大以满足每个副本的负载。否则支出检查可能在等待连接时[超时](/docs/zh-CN/claude-apps-gateway-spend-limits.md#postgres-availability),网关会记录 `spend check failed: spend precheck timed out`。290* **连接池**:降低 `store.max_connections`,但在启用[支出限制](https://code.claude.com/docs/zh-CN/claude-apps-gateway-spend-limits.md)时,请使其足够大以满足每个副本的负载。否则支出检查可能在等待连接时[超时](https://code.claude.com/docs/zh-CN/claude-apps-gateway-spend-limits.md#postgres-availability),网关会记录 `spend check failed: spend precheck timed out`。
277 291
278### 升级292### 升级
279 293
308| 数据 | 路径 | 由网关发送给 Anthropic |322| 数据 | 路径 | 由网关发送给 Anthropic |
309| - | - | - |323| - | - | - |
310| 推理(提示、完成) | CLI → 网关 → 您的上游 | 仅当 Anthropic API 是配置的上游时 |324| 推理(提示、完成) | CLI → 网关 → 您的上游 | 仅当 Anthropic API 是配置的上游时 |
311| 遥测(OTLP 指标,加上 [选择加入日志和跟踪](/docs/zh-CN/claude-apps-gateway-config.md#telemetry)) | CLI → 网关 → 您的收集器 | 从不 |325| 遥测(OTLP 指标,加上 [选择加入日志和跟踪](https://code.claude.com/docs/zh-CN/claude-apps-gateway-config.md#telemetry)) | CLI → 网关 → 您的收集器 | 从不 |
312| 身份(电子邮件、组、sub) | IdP → 网关 → CLI;CLI 在 OTLP 导出上标记它。如果您打开 [`forward_user_identity`](/docs/zh-CN/claude-apps-gateway-config#per-user-identity-headers-for-a-proxy-you-run),网关也会将开发者的电子邮件和 IdP 主体作为标头发送到您的代理 | 从不 |326| 身份(电子邮件、组、sub) | IdP → 网关 → CLI;CLI 在 OTLP 导出上标记它。如果您打开 [`forward_user_identity`](https://code.claude.com/docs/zh-CN/claude-apps-gateway-config#per-user-identity-headers-for-a-proxy-you-run),网关也会将开发者的电子邮件和 IdP 主体作为标头发送到您的代理 | 从不 |
313| 托管设置 | 您的网关 YAML → CLI | 从不 |327| 托管设置 | 您的网关 YAML → CLI | 从不 |
314| 审计日志 | 网关 stderr → 您的聚合器 | 从不 |328| 审计日志 | 网关 stderr → 您的聚合器 | 从不 |
315 329
321* 设备验证页面强制执行同源 POST 和每个 RFC 8628 §5.1 的每 IP 速率限制。请参阅 [用户代码暴力破解抵抗](#user-code-brute-force-resistance)。335* 设备验证页面强制执行同源 POST 和每个 RFC 8628 §5.1 的每 IP 速率限制。请参阅 [用户代码暴力破解抵抗](#user-code-brute-force-resistance)。
322* 网关对您的 IdP、您的 OTLP 收集器和 `provider: anthropic` 上游的请求通过服务器端请求伪造 (SSRF) 防护,解析 DNS,阻止链接本地和云元数据地址加上默认的本地环回,并将连接固定到解析的 IP,因此操作员影响的 URL 无法重定向到云元数据端点。RFC 1918 私有范围被故意允许,因为 IdP 和 OTLP 收集器通常存在于私有 IP 上。对于其他提供商,网关在加载配置时拒绝命名这些地址或元数据主机名之一的 `base_url`,然后提供商的 SDK 连接而不进行 DNS 检查。336* 网关对您的 IdP、您的 OTLP 收集器和 `provider: anthropic` 上游的请求通过服务器端请求伪造 (SSRF) 防护,解析 DNS,阻止链接本地和云元数据地址加上默认的本地环回,并将连接固定到解析的 IP,因此操作员影响的 URL 无法重定向到云元数据端点。RFC 1918 私有范围被故意允许,因为 IdP 和 OTLP 收集器通常存在于私有 IP 上。对于其他提供商,网关在加载配置时拒绝命名这些地址或元数据主机名之一的 `base_url`,然后提供商的 SDK 连接而不进行 DNS 检查。
323 337
324 如果您打开 [仅代理出口](/docs/zh-CN/claude-apps-gateway-config.md#proxy-only-egress),该地址检查会移到您的转发代理:网关交付主机名,代理的允许列表必须拒绝这些目的地。338 如果您打开 [仅代理出口](https://code.claude.com/docs/zh-CN/claude-apps-gateway-config.md#proxy-only-egress),该地址检查会移到您的转发代理:网关交付主机名,代理的允许列表必须拒绝这些目的地。
325 339
326 仅当网关必须合法到达的某些内容存在于本地环回时(例如本地开发 IdP 或 `localhost` 上的 sidecar OTLP 收集器),在网关的环境中设置 `CLAUDE_GATEWAY_ALLOW_LOOPBACK=1`。该变量为每个操作员配置的 URL 放宽本地环回块,也跳过启动时警告,该警告检查 pod 是否可以到达云元数据端点,因此更倾向于为收集器提供其自己的内部地址。340 仅当网关必须合法到达的某些内容存在于本地环回时(例如本地开发 IdP 或 `localhost` 上的 sidecar OTLP 收集器),在网关的环境中设置 `CLAUDE_GATEWAY_ALLOW_LOOPBACK=1`。该变量为每个操作员配置的 URL 放宽本地环回块,也跳过启动时警告,该警告检查 pod 是否可以到达云元数据端点,因此更倾向于为收集器提供其自己的内部地址。
327 341
329 343
330两个威胁超出范围,因为它们是您的基础设施来保护:344两个威胁超出范围,因为它们是您的基础设施来保护:
331 345
332* **受损的网关主机**:主机既持有上游凭证,又向每个连接的开发者分发 [托管设置](/docs/zh-CN/claude-apps-gateway-config.md#managed),因此对网关配置的控制与对您的 MDM 的控制相当。CLI 的 [批准对话框](/docs/zh-CN/server-managed-settings.md#approval-memory) 用于 shell 能力设置限制无声更改,但不替代主机安全。346* **受损的网关主机**:主机既持有上游凭证,又向每个连接的开发者分发 [托管设置](https://code.claude.com/docs/zh-CN/claude-apps-gateway-config.md#managed),因此对网关配置的控制与对您的 MDM 的控制相当。CLI 的 [批准对话框](https://code.claude.com/docs/zh-CN/server-managed-settings.md#approval-memory) 用于 shell 能力设置限制无声更改,但不替代主机安全。
333* **恶意 OIDC 提供商**:提供商签署网关信任的 id\_tokens,因此它可以声称任何身份。审查和保护您的 IdP 是您的责任。347* **恶意 OIDC 提供商**:提供商签署网关信任的 id\_tokens,因此它可以声称任何身份。审查和保护您的 IdP 是您的责任。
334 348
335### 用户代码暴力破解抵抗349### 用户代码暴力破解抵抗
336 350
337开发者在 `/device` 验证页面中输入的 `user_code` 是从 20 字符字母表中抽取的 8 个字符,产生 20⁸ 或约 2.56×10¹⁰ 个组合,在 10 分钟后过期。351开发者在 `/device` 验证页面中输入的 `user_code` 是从 20 字符字母表中抽取的 8 个字符,产生 20⁸ 或约 2.56×10¹⁰ 个组合,在 10 分钟后过期。
338 352
339网关在设备授权端点上应用按 IP 速率限制,可通过 [`rate_limits`](/docs/zh-CN/claude-apps-gateway-config#http-tuning) 配置。如果许多开发者从单个共享公司 NAT 地址登录,提高限制。[大规模推出](#large-rollouts) 显示如何调整它们的大小。限制仅适用于登录流,不适用于推理。353网关在设备授权端点上应用按 IP 速率限制,可通过 [`rate_limits`](https://code.claude.com/docs/zh-CN/claude-apps-gateway-config#http-tuning) 配置。如果许多开发者从单个共享公司 NAT 地址登录,提高限制。[大规模推出](#large-rollouts) 显示如何调整它们的大小。限制仅适用于登录流,不适用于推理。
340 354
341### 合规性态势355### 合规性态势
342 356
343* **数据驻留**:网关自己的数据平面除非 Anthropic API 是配置的上游,否则不向 Anthropic 发送任何内容;当它是时,您现有的数据处理协议适用于推理路径。遥测、审计、身份和设置仅去往您配置的目的地。357* **数据驻留**:网关自己的数据平面除非 Anthropic API 是配置的上游,否则不向 Anthropic 发送任何内容;当它是时,您现有的数据处理协议适用于推理路径。遥测、审计、身份和设置仅去往您配置的目的地。
344* **主机进程流量**:主机进程是 Claude Code CLI。`claude gateway` 在与 Amazon Bedrock 和 Google Cloud 的 Agent Platform 部署相同的第三方规则下运行,不向 Anthropic 发送任何内容。在 v2.1.227 之前,主机进程发送启动遥测,例如产品版本和平台,在容器环境中设置 `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1` 关闭。这些版本也在启动时发送一个 `HEAD` 请求,没有正文或凭证,到 `https://api.anthropic.com` 上的 `/api/hello`,或在环境设置时的 `ANTHROPIC_BASE_URL` 上,除非环境也设置了代理变量(如 `HTTPS_PROXY`)或 mTLS 客户端证书。它们忽略了响应,因此在出口防火墙处阻止该请求不影响网关。358* **主机进程流量**:主机进程是 Claude Code CLI。`claude gateway` 在与 Amazon Bedrock 和 Google Cloud 的 Agent Platform 部署相同的第三方规则下运行,不向 Anthropic 发送任何内容。在 v2.1.227 之前,主机进程发送启动遥测,例如产品版本和平台,在容器环境中设置 `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1` 关闭。这些版本也在启动时发送一个 `HEAD` 请求,没有正文或凭证,到 `https://api.anthropic.com` 上的 `/api/hello`,或在环境设置时的 `ANTHROPIC_BASE_URL` 上,除非环境也设置了代理变量(如 `HTTPS_PROXY`)或 mTLS 客户端证书。它们忽略了响应,因此在出口防火墙处阻止该请求不影响网关。
345* **客户端分析**:CLI 在登录到网关时禁用自己的使用分析和错误报告。在第一次登录之前,CLI 仍然向 Anthropic 发送启动事件,包括在托管设置强制网关登录的机器上。要保持这些关闭,在强制网关登录的相同 [客户端托管设置](/docs/zh-CN/claude-apps-gateway-config.md#client-side-managed-settings) 中传递 [`DISABLE_TELEMETRY`](/docs/zh-CN/managed-settings#turn-telemetry-off-for-your-organization)。359* **客户端分析**:CLI 在登录到网关时禁用自己的使用分析和错误报告。在第一次登录之前,CLI 仍然向 Anthropic 发送启动事件,包括在托管设置强制网关登录的机器上。要保持这些关闭,在强制网关登录的相同 [客户端托管设置](https://code.claude.com/docs/zh-CN/claude-apps-gateway-config.md#client-side-managed-settings) 中传递 [`DISABLE_TELEMETRY`](https://code.claude.com/docs/zh-CN/managed-settings#turn-telemetry-off-for-your-organization)。
346* **错误报告**:每当 CLI 的模型请求去往 Anthropic 的第一方 API 以外的任何端点(如 Amazon Bedrock 或自定义 `ANTHROPIC_BASE_URL`)时,CLI 关闭错误报告。360* **错误报告**:每当 CLI 的模型请求去往 Anthropic 的第一方 API 以外的任何端点(如 Amazon Bedrock 或自定义 `ANTHROPIC_BASE_URL`)时,CLI 关闭错误报告。
347* **客户端机器**:开发者的 CLI 仍然向 Anthropic 发送 WebFetch 主机名检查和版本检查,除非设置了 `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1` 和 `skipWebFetchPreflight: true`。[插件市场请求](#plugin-marketplace-requests) 有各自的关闭开关。请参阅 [数据使用](/docs/zh-CN/data-usage.md)。361* **客户端机器**:开发者的 CLI 仍然向 Anthropic 发送 WebFetch 主机名检查和版本检查,除非设置了 `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1` 和 `skipWebFetchPreflight: true`。[插件市场请求](#plugin-marketplace-requests) 有各自的关闭开关。请参阅 [数据使用](https://code.claude.com/docs/zh-CN/data-usage.md)。
348* **调查评分**:在登录到网关时,CLI 禁用 Anthropic 绑定的评分上传以及分析流,因此它不向 Anthropic 发送评分。362* **调查评分**:在登录到网关时,CLI 禁用 Anthropic 绑定的评分上传以及分析流,因此它不向 Anthropic 发送评分。
349* **成绩单共享**:在调查的成绩单共享提示上选择"是"会在 `~/.claude/feedback-bundles/` 下写入本地文件,而不是上传到 Anthropic。363* **成绩单共享**:在调查的成绩单共享提示上选择"是"会在 `~/.claude/feedback-bundles/` 下写入本地文件,而不是上传到 Anthropic。
350* **客户端更新**:更新检查与网关流量分开。通过您自己的分发固定版本,如果笔记本电脑不得获取版本,设置 `DISABLE_UPDATES`。`DISABLE_AUTOUPDATER` 仅停止后台更新,而 `claude update` 仍然有效。364* **客户端更新**:更新检查与网关流量分开。通过您自己的分发固定版本,如果笔记本电脑不得获取版本,设置 `DISABLE_UPDATES`。`DISABLE_AUTOUPDATER` 仅停止后台更新,而 `claude update` 仍然有效。
351* **TLS**:在生产中通过 HTTPS 提供 `public_url`,要么从网关自己的监听器通过 `listen.tls`,要么从 TLS 终止入口在普通 HTTP 副本前面,在两种情况下都设置 `listen.public_url`。网关不拒绝普通 HTTP。IdP 必须在生产中提供 HTTPS,Postgres 支持 `?sslmode=require`。在您的入口处设置 `Strict-Transport-Security`。365* **TLS**:在生产中通过 HTTPS 提供 `public_url`,要么从网关自己的监听器通过 `listen.tls`,要么从 TLS 终止入口在普通 HTTP 副本前面,在两种情况下都设置 `listen.public_url`。网关不拒绝普通 HTTP。IdP 必须在生产中提供 HTTPS,Postgres 支持 `?sslmode=require`。在您的入口处设置 `Strict-Transport-Security`。
352* **漏洞披露**:遵循 [报告安全问题](/docs/zh-CN/security.md#reporting-security-issues)366* **漏洞披露**:遵循 [报告安全问题](https://code.claude.com/docs/zh-CN/security.md#reporting-security-issues)
353 367
354### 插件市场请求368### 插件市场请求
355 369
356Claude Code 直接从每位开发者的机器获取插件市场,而不是通过网关。[网络访问要求](/docs/zh-CN/network-config.md#network-access-requirements) 列出了相关主机。370Claude Code 直接从每位开发者的机器获取插件市场,而不是通过网关。[网络访问要求](https://code.claude.com/docs/zh-CN/network-config.md#network-access-requirements) 列出了相关主机。
357 371
358开发者首次启动交互式终端会话时,Claude Code 会注册官方市场 `claude-plugins-official`。它从 `downloads.claude.ai` 下载目录,如果失败,则从 `github.com` 克隆。[哪些市场和插件会自动更新](/docs/zh-CN/plugins/loading.md#which-marketplaces-and-plugins-auto-update) 介绍了后续刷新。372开发者首次启动交互式终端会话时,Claude Code 会注册官方市场 `claude-plugins-official`。它从 `downloads.claude.ai` 下载目录,如果失败,则从 `github.com` 克隆。[哪些市场和插件会自动更新](https://code.claude.com/docs/zh-CN/plugins/loading.md#which-marketplaces-and-plugins-auto-update) 介绍了后续刷新。
359 373
360`CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1` 不会阻止首次注册。以下任一托管设置可以阻止:374`CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1` 不会阻止首次注册。以下任一托管设置可以阻止:
361 375
362* **市场列表**:不包含该市场的 [`strictKnownMarketplaces`](/docs/zh-CN/plugins/org#allowlist-with-strictknownmarketplaces) 允许列表,或指明该市场的 [`blockedMarketplaces`](/docs/zh-CN/plugins/org#blocklist-with-blockedmarketplaces) 条目376* **市场列表**:不包含该市场的 [`strictKnownMarketplaces`](https://code.claude.com/docs/zh-CN/plugins/org#allowlist-with-strictknownmarketplaces) 允许列表,或指明该市场的 [`blockedMarketplaces`](https://code.claude.com/docs/zh-CN/plugins/org#blocklist-with-blockedmarketplaces) 条目
363* **环境变量**:在托管的 [`env` 块](/docs/zh-CN/plugins/org#turn-updates-off-for-the-whole-fleet) 中将 `CLAUDE_CODE_DISABLE_OFFICIAL_MARKETPLACE_AUTOINSTALL` 设置为 `"1"`377* **环境变量**:在托管的 [`env` 块](https://code.claude.com/docs/zh-CN/plugins/org#turn-updates-off-for-the-whole-fleet) 中将 `CLAUDE_CODE_DISABLE_OFFICIAL_MARKETPLACE_AUTOINSTALL` 设置为 `"1"`
364 378
365首次注册可能在开发者登录网关之前运行,此时尚未收到任何网关策略。为覆盖首次启动,请在 [客户端托管设置](/docs/zh-CN/claude-apps-gateway-config.md#client-side-managed-settings) 以及网关策略的 [`cli` 或 `code` 块](/docs/zh-CN/claude-apps-gateway-config#what-goes-in-cli) 中同时传递您的选择。379首次注册可能在开发者登录网关之前运行,此时尚未收到任何网关策略。为覆盖首次启动,请在 [客户端托管设置](https://code.claude.com/docs/zh-CN/claude-apps-gateway-config.md#client-side-managed-settings) 以及网关策略的 [`cli` 或 `code` 块](https://code.claude.com/docs/zh-CN/claude-apps-gateway-config#what-goes-in-cli) 中同时传递您的选择。
366 380
367## 故障排除381## 故障排除
368 382
376 390
377| 症状 | 原因 | 解决方案 |391| 症状 | 原因 | 解决方案 |
378| - | - | - |392| - | - | - |
379| 开发者的 `/login` 显示标准账户选择器而不是 **Cloud gateway** 屏幕 | 该机器的托管设置中未设置 `forceLoginMethod` 或 `forceLoginGatewayUrl` | 将[托管设置文件](/docs/zh-CN/claude-apps-gateway#set-the-gateway-url)部署到设备;`/login` 从那里读取网关 URL |393| 开发者的 `/login` 显示标准账户选择器而不是 **Cloud gateway** 屏幕 | 该机器的托管设置中未设置 `forceLoginMethod` 或 `forceLoginGatewayUrl` | 将[托管设置文件](https://code.claude.com/docs/zh-CN/claude-apps-gateway#set-the-gateway-url)部署到设备;`/login` 从那里读取网关 URL |
380| 开发者的请求失败,显示 `Not signed in to the Cloud gateway — run /login.` | 机器的托管设置设置了 `forceLoginMethod: "gateway"` 或 `forceLoginGatewayUrl`,且会话没有网关登录。残留的 claude.ai 登录不满足要求。 | 让开发者运行 `/login` 并完成网关登录。另请参阅[管理员策略需要 Cloud gateway 登录](/docs/zh-CN/errors.md#administrator-policy-requires-a-cloud-gateway-sign-in)。 |394| 开发者的请求失败,显示 `Not signed in to the Cloud gateway — run /login.` | 机器的托管设置设置了 `forceLoginMethod: "gateway"` 或 `forceLoginGatewayUrl`,且会话没有网关登录。残留的 claude.ai 登录不满足要求。 | 让开发者运行 `/login` 并完成网关登录。另请参阅[管理员策略需要 Cloud gateway 登录](https://code.claude.com/docs/zh-CN/errors.md#administrator-policy-requires-a-cloud-gateway-sign-in)。 |
381| Claude Desktop 报告其引导配置无法获取 | `/user/bootstrap` 返回 404:与用户匹配的策略不包含 `desktop` 键,或没有策略匹配。网关的审计日志将每次拒绝记录为 `desktop_bootstrap.denied` 并说明原因。 | 将 `desktop` 块添加到与用户匹配的策略,或添加到 `match: {}` 基础层;空的 `desktop: {}` 就足够了。请参阅 [Claude Desktop 覆盖](/docs/zh-CN/claude-apps-gateway-config.md#claude-desktop-overlay)。 |395| Claude Desktop 报告其引导配置无法获取 | `/user/bootstrap` 返回 404:与用户匹配的策略不包含 `desktop` 键,或没有策略匹配。网关的审计日志将每次拒绝记录为 `desktop_bootstrap.denied` 并说明原因。 | 将 `desktop` 块添加到与用户匹配的策略,或添加到 `match: {}` 基础层;空的 `desktop: {}` 就足够了。请参阅 [Claude Desktop 覆盖](https://code.claude.com/docs/zh-CN/claude-apps-gateway-config.md#claude-desktop-overlay)。 |
382| 启动显示 `Gateway login is configured in managed settings, but this Claude Code build does not include Cloud gateway support.` | 已安装的 Claude Code 版本早于网关支持 | 让开发者更新 Claude Code 到包含 Cloud gateway 支持的版本 |396| 启动显示 `Gateway login is configured in managed settings, but this Claude Code build does not include Cloud gateway support.` | 已安装的 Claude Code 版本早于网关支持 | 让开发者更新 Claude Code 到包含 Cloud gateway 支持的版本 |
383| 启动退出,显示 `Administrator policy requires a Cloud gateway sign-in on this machine` | 开发者的环境设置了 `ANTHROPIC_API_KEY` 或 `ANTHROPIC_AUTH_TOKEN`,其设置配置了 [`apiKeyHelper`](/docs/zh-CN/settings-reference#apikeyhelper),或来自早期 Claude Console 登录的 API 密钥仍然保存 | 让开发者清除每个适用的项:取消设置变量、删除 `apiKeyHelper` 条目,或运行 `claude auth logout` 删除保存的密钥。之后,使用 `CLAUDE_CODE_USE_*` 选择云提供商的会话无需登录即可启动;对于其他所有会话,让他们启动 `claude` 并使用 `/login` 登录。另请参阅[管理员策略需要 Cloud gateway 登录](/docs/zh-CN/errors.md#administrator-policy-requires-a-cloud-gateway-sign-in)。 |397| 启动退出,显示 `Administrator policy requires a Cloud gateway sign-in on this machine` | 开发者的环境设置了 `ANTHROPIC_API_KEY` 或 `ANTHROPIC_AUTH_TOKEN`,其设置配置了 [`apiKeyHelper`](https://code.claude.com/docs/zh-CN/settings-reference#apikeyhelper),或来自早期 Claude Console 登录的 API 密钥仍然保存 | 让开发者清除每个适用的项:取消设置变量、删除 `apiKeyHelper` 条目,或运行 `claude auth logout` 删除保存的密钥。之后,使用 `CLAUDE_CODE_USE_*` 选择云提供商的会话无需登录即可启动;对于其他所有会话,让他们启动 `claude` 并使用 `/login` 登录。另请参阅[管理员策略需要 Cloud gateway 登录](https://code.claude.com/docs/zh-CN/errors.md#administrator-policy-requires-a-cloud-gateway-sign-in)。 |
384| 启动或 `/login` 在托管设置加载时返回 403 后报告 `Claude Code may not be enabled for your organization` | 网关或其前面的某个组件用 403 响应了 `/managed/settings` 请求。网关自身的设置路由从不返回 403。状态来自 [`access_control`](/docs/zh-CN/claude-apps-gateway-config#http-tuning) IP 检查或网关前面的代理或 WAF。审计日志将 IP 检查拒绝记录为 `access.denied` 并说明原因。开发者保持登录状态。 | 检查审计日志中失败时的 `access.denied`,修复 `access_control` 列表或前端,然后让开发者再次启动 `claude` |398| 启动或 `/login` 在托管设置加载时返回 403 后报告 `Claude Code may not be enabled for your organization` | 网关或其前面的某个组件用 403 响应了 `/managed/settings` 请求。网关自身的设置路由从不返回 403。状态来自 [`access_control`](https://code.claude.com/docs/zh-CN/claude-apps-gateway-config#http-tuning) IP 检查或网关前面的代理或 WAF。审计日志将 IP 检查拒绝记录为 `access.denied` 并说明原因。开发者保持登录状态。 | 检查审计日志中失败时的 `access.denied`,修复 `access_control` 列表或前端,然后让开发者再次启动 `claude` |
385| CLI `/login`:`The gateway is limiting sign-in attempts right now`,或在较旧版本上 `Request failed with status code 429`。`/device` 页面可能向尚未尝试过的开发者显示 `Too many attempts` | 达到了每 IP 登录速率限制。要么 `listen.trusted_proxies` 不覆盖负载均衡器,所以每个开发者共享其地址,要么许多开发者共享一个 NAT 或 VPN 出口地址。具有 `result: rate_limited` 的审计事件显示相同的一个或几个 `client_ip` 值。 | 首先将 `listen.trusted_proxies` 设置为负载均衡器的源范围,然后如果开发者仍然共享地址,提高 `rate_limits`。请参阅[大规模推出](#large-rollouts)。 |399| CLI `/login`:`The gateway is limiting sign-in attempts right now`,或在较旧版本上 `Request failed with status code 429`。`/device` 页面可能向尚未尝试过的开发者显示 `Too many attempts` | 达到了每 IP 登录速率限制。要么 `listen.trusted_proxies` 不覆盖负载均衡器,所以每个开发者共享其地址,要么许多开发者共享一个 NAT 或 VPN 出口地址。具有 `result: rate_limited` 的审计事件显示相同的一个或几个 `client_ip` 值。 | 首先将 `listen.trusted_proxies` 设置为负载均衡器的源范围,然后如果开发者仍然共享地址,提高 `rate_limits`。请参阅[大规模推出](#large-rollouts)。 |
386| CLI `/login`:`Gateway hosts must be on your organization's private network; <host> resolves to the public (or unrecognized) address <ip>` | 网关主机名解析为至少一个公网 IP 地址。Claude Code 检查每个解析的地址,要求每个都是私网。常见原因是双栈名称,其中一个族解析为公网地址,包括 AWS 内部双栈负载均衡器,它们返回公网范围的 AAAA 地址。 | 让网关名称在开发者机器上仅解析为私网地址。对于双栈名称,删除公网范围的记录或提供单独的仅内部 DNS 名称。请参阅[私网前提条件](/docs/zh-CN/claude-apps-gateway#prerequisites)。如果地址是您的组织拥有并在内部使用的公网空间,请[声明该块](/docs/zh-CN/claude-apps-gateway#allow-a-gateway-on-public-address-space-you-own)。 |400| CLI `/login`:`Gateway hosts must be on your organization's private network; <host> resolves to the public (or unrecognized) address <ip>` | 网关主机名解析为至少一个公网 IP 地址。Claude Code 检查每个解析的地址,要求每个都是私网。常见原因是双栈名称,其中一个族解析为公网地址,包括 AWS 内部双栈负载均衡器,它们返回公网范围的 AAAA 地址。 | 让网关名称在开发者机器上仅解析为私网地址。对于双栈名称,删除公网范围的记录或提供单独的仅内部 DNS 名称。请参阅[私网前提条件](https://code.claude.com/docs/zh-CN/claude-apps-gateway#prerequisites)。如果地址是您的组织拥有并在内部使用的公网空间,请[声明该块](https://code.claude.com/docs/zh-CN/claude-apps-gateway#allow-a-gateway-on-public-address-space-you-own)。 |
387| CLI `/login`:`Gateway login would go through proxy <proxy>, which is not on a private network` | `HTTPS_PROXY` 或 `HTTP_PROXY` 适用于网关主机,且代理的主机名解析为公网地址。主机名仅解析为私网地址的代理是允许的,不会触发此错误 | 在开发者的机器上将网关主机添加到 `NO_PROXY`,以便连接是直接的,或使用主机名解析为私网地址的代理。消息会命名要添加的确切 `NO_PROXY` 条目 |401| CLI `/login`:`Gateway login would go through proxy <proxy>, which is not on a private network` | `HTTPS_PROXY` 或 `HTTP_PROXY` 适用于网关主机,且代理的主机名解析为公网地址。主机名仅解析为私网地址的代理是允许的,不会触发此错误 | 在开发者的机器上将网关主机添加到 `NO_PROXY`,以便连接是直接的,或使用主机名解析为私网地址的代理。消息会命名要添加的确切 `NO_PROXY` 条目 |
388| CLI `/login`:`Claude Code only signs in to <host> from inside its declared network <block> (managed settings), and this machine is connecting from <ip>, outside it` | 网关在 [`gatewayInternalNetworks`](/docs/zh-CN/claude-apps-gateway#allow-a-gateway-on-public-address-space-you-own) 中声明的块上,开发者的机器从该块外的地址到达它:VPN 地址池、容器或 WSL2 NAT 段,或不是您的网络 | 让开发者从您的网络上的主机 OS 运行 `/login`。如果显示的地址也是您的组织自己的公网空间,将网关的条目替换为覆盖两者的块,最多 `/8`;第二个重叠条目会被拒绝。如果没有能覆盖两者的块,请参阅[为网关选择地址](#choose-an-address-for-the-gateway) |402| CLI `/login`:`Claude Code only signs in to <host> from inside its declared network <block> (managed settings), and this machine is connecting from <ip>, outside it` | 网关在 [`gatewayInternalNetworks`](https://code.claude.com/docs/zh-CN/claude-apps-gateway#allow-a-gateway-on-public-address-space-you-own) 中声明的块上,开发者的机器从该块外的地址到达它:VPN 地址池、容器或 WSL2 NAT 段,或不是您的网络 | 让开发者从您的网络上的主机 OS 运行 `/login`。如果显示的地址也是您的组织自己的公网空间,将网关的条目替换为覆盖两者的块,最多 `/8`;第二个重叠条目会被拒绝。如果没有能覆盖两者的块,请参阅[为网关选择地址](#choose-an-address-for-the-gateway) |
389| CLI `/login`:`Every address for gateway host <host> must be inside its declared network <block>, and it also resolves to <ip>` | 网关的名称解析为 [`gatewayInternalNetworks`](/docs/zh-CN/claude-apps-gateway#allow-a-gateway-on-public-address-space-you-own) 中声明的块外的地址:第二个站点,或双栈名称上的 IPv6 记录。在声明的块下,每条记录都必须在该单个 IPv4 块内,包括私网和 IPv6 地址 | 在开发者机器上仅为网关名称发布块内的记录,或提供单独的仅内部名称 |403| CLI `/login`:`Every address for gateway host <host> must be inside its declared network <block>, and it also resolves to <ip>` | 网关的名称解析为 [`gatewayInternalNetworks`](https://code.claude.com/docs/zh-CN/claude-apps-gateway#allow-a-gateway-on-public-address-space-you-own) 中声明的块外的地址:第二个站点,或双栈名称上的 IPv6 记录。在声明的块下,每条记录都必须在该单个 IPv4 块内,包括私网和 IPv6 地址 | 在开发者机器上仅为网关名称发布块内的记录,或提供单独的仅内部名称 |
390| CLI `/login`:`<host> is on the declared network <block>, which Claude Code checks over a direct connection, not through an HTTP proxy` | `HTTPS_PROXY` 或 `HTTP_PROXY` 适用于声明块上的网关 | 在开发者的机器上,添加消息命名的 `NO_PROXY` 条目 |404| CLI `/login`:`<host> is on the declared network <block>, which Claude Code checks over a direct connection, not through an HTTP proxy` | `HTTPS_PROXY` 或 `HTTP_PROXY` 适用于声明块上的网关 | 在开发者的机器上,添加消息命名的 `NO_PROXY` 条目 |
391| CLI `/login`:消息以 `gatewayInternalNetworks in managed settings` 开头 | 该值违反了[验证规则](/docs/zh-CN/claude-apps-gateway#allow-a-gateway-on-public-address-space-you-own)之一,消息会命名哪一个。在您修复它之前,Claude Code 拒绝机器上的每个新网关 `/login`,包括私网上的网关;现有登录保持工作 | 在您部署的托管设置源中,更正消息命名的条目,然后重新运行 `/login` |405| CLI `/login`:消息以 `gatewayInternalNetworks in managed settings` 开头 | 该值违反了[验证规则](https://code.claude.com/docs/zh-CN/claude-apps-gateway#allow-a-gateway-on-public-address-space-you-own)之一,消息会命名哪一个。在您修复它之前,Claude Code 拒绝机器上的每个新网关 `/login`,包括私网上的网关;现有登录保持工作 | 在您部署的托管设置源中,更正消息命名的条目,然后重新运行 `/login` |
392| CLI `/login`:`Could not resolve the configured HTTP proxy` | `HTTPS_PROXY` 或 `HTTP_PROXY` 中的主机名无法从开发者的机器解析,通常是因为它未连接到公司网络 | 让开发者连接到您的网络或 VPN 并重试,或修复代理 URL |406| CLI `/login`:`Could not resolve the configured HTTP proxy` | `HTTPS_PROXY` 或 `HTTP_PROXY` 中的主机名无法从开发者的机器解析,通常是因为它未连接到公司网络 | 让开发者连接到您的网络或 VPN 并重试,或修复代理 URL |
393| CLI `/login`:`Could not resolve gateway host <host>` | 机器无法解析网关的内部 DNS 名称,通常是因为它不在公司网络上 | 让开发者连接到您的网络或 VPN,然后重试 `/login` |407| CLI `/login`:`Could not resolve gateway host <host>` | 机器无法解析网关的内部 DNS 名称,通常是因为它不在公司网络上 | 让开发者连接到您的网络或 VPN,然后重试 `/login` |
394| 启动退出,显示配置验证错误,命名 `store.postgres_url` | 未配置 Postgres;网关需要 Postgres | 设置 `store.postgres_url`。对于本地开发,使用一次性容器:`docker run --rm -p 5432:5432 -e POSTGRES_HOST_AUTH_METHOD=trust postgres`。 |408| 启动退出,显示配置验证错误,命名 `store.postgres_url` | 未配置 Postgres;网关需要 Postgres | 设置 `store.postgres_url`。对于本地开发,使用一次性容器:`docker run --rm -p 5432:5432 -e POSTGRES_HOST_AUTH_METHOD=trust postgres`。 |
395| 启动退出:`store.postgres_url in <path> is not a URL the gateway can read`,或在 v2.1.290 之前仅显示 `Invalid URL` 或 `URI error` | 无法解析该 URL,例如因为它列出了多个主机,或其密码包含未编码的 `/`、`?`、`#` 或 `%` | 仅指定[一个主机](#postgres),并将密码移到 [`store.password`](/docs/zh-CN/claude-apps-gateway-config#store) 中 |409| 启动退出:`store.postgres_url in <path> is not a URL the gateway can read`,或在 v2.1.290 之前仅显示 `Invalid URL` 或 `URI error` | 无法解析该 URL,例如因为它列出了多个主机,或其密码包含未编码的 `/`、`?`、`#` 或 `%` | 仅指定[一个主机](#postgres),并将密码移到 [`store.password`](https://code.claude.com/docs/zh-CN/claude-apps-gateway-config#store) 中 |
396| 启动退出:`requires the native binary` | 在 Node 下运行而不是本地二进制 | 使用[独立安装方法](/docs/zh-CN/setup.md)之一安装 Claude Code |410| 启动退出:`requires the native binary` | 在 Node 下运行而不是本地二进制 | 使用[独立安装方法](https://code.claude.com/docs/zh-CN/setup.md)之一安装 Claude Code |
397| 启动退出,在 `config.load` 后显示 OIDC 发现错误 | `oidc.issuer` 无法访问,或 TLS 链不受信任 | 检查发行者是否可从 pod 访问并提供 `/.well-known/openid-configuration`。为私有 PKI 设置 `ca_cert_pem`。如果 pod 仅通过前向代理到达 IdP,设置 [`oidc.use_proxy: true`](/docs/zh-CN/claude-apps-gateway-config#idp-requests-through-a-forward-proxy);在 v2.1.227 之前的版本上,改为给 pod 一条到 IdP 每个端点的直接路由。如果 pod 也无法解析 IdP 的主机名,或代理拒绝 `CONNECT` 到 IP 地址,请参阅[仅代理出口](/docs/zh-CN/claude-apps-gateway-config.md#proxy-only-egress),这需要 v2.1.277 或更高版本。 |411| 启动退出,在 `config.load` 后显示 OIDC 发现错误 | `oidc.issuer` 无法访问,或 TLS 链不受信任 | 检查发行者是否可从 pod 访问并提供 `/.well-known/openid-configuration`。为私有 PKI 设置 `ca_cert_pem`。如果 pod 仅通过前向代理到达 IdP,设置 [`oidc.use_proxy: true`](https://code.claude.com/docs/zh-CN/claude-apps-gateway-config#idp-requests-through-a-forward-proxy);在 v2.1.227 之前的版本上,改为给 pod 一条到 IdP 每个端点的直接路由。如果 pod 也无法解析 IdP 的主机名,或代理拒绝 `CONNECT` 到 IP 地址,请参阅[仅代理出口](https://code.claude.com/docs/zh-CN/claude-apps-gateway-config.md#proxy-only-egress),这需要 v2.1.277 或更高版本。 |
398| 启动退出,显示 Postgres 权限错误 | 数据库角色在其 schema 上缺少 DDL 权限 | 授予角色对网关 schema 的 `CREATE` 权限,以便它可以在启动时创建和修改其表 |412| 启动退出,显示 Postgres 权限错误 | 数据库角色在其 schema 上缺少 DDL 权限 | 授予角色对网关 schema 的 `CREATE` 权限,以便它可以在启动时创建和修改其表 |
399| 日志:来自 PostgreSQL 的 `remaining connection slots are reserved` 或 `sorry, too many clients already`。它出现在正在运行的副本的 `postgres connection closed` 警告中,或新副本的启动日志中。在启动日志中,`remaining connection slots are reserved` 可能出现在 `attempt 1 of 3` 之后,且该副本仍可能启动。 | 副本请求的连接数超过了数据库为网关剩余的连接数,PostgreSQL 拒绝了多出的连接 | 按照[调整连接池大小](#size-the-connection-pool)中的说明使总数符合限制:运行更少的副本、降低 `store.max_connections`,或提高数据库的 `max_connections`。如果总数仅在滚动更新期间超出,而您的编排器支持,也可以让编排器在启动新副本之前先停止旧副本。 |413| 日志:来自 PostgreSQL 的 `remaining connection slots are reserved` 或 `sorry, too many clients already`。它出现在正在运行的副本的 `postgres connection closed` 警告中,或新副本的启动日志中。在启动日志中,`remaining connection slots are reserved` 可能出现在 `attempt 1 of 3` 之后,且该副本仍可能启动。 | 副本请求的连接数超过了数据库为网关剩余的连接数,PostgreSQL 拒绝了多出的连接 | 按照[调整连接池大小](#size-the-connection-pool)中的说明使总数符合限制:运行更少的副本、降低 `store.max_connections`,或提高数据库的 `max_connections`。如果总数仅在滚动更新期间超出,而您的编排器支持,也可以让编排器在启动新副本之前先停止旧副本。 |
400| 日志:`could not connect to Postgres at boot, attempt 1 of 3`,且原因不是 `remaining connection slots are reserved` | 网关启动时数据库尚无法访问,例如在网络仍在启动的冷实例上 | 如果网关随后完成启动,无需采取任何措施。当数据库无法访问时,网关在退出前尝试连接三次,间隔两秒。如果它以 `could not connect to Postgres` 退出,检查 `store.postgres_url`(包括它是否只指定了一个主机)以及到数据库的网络路径。如果尝试超时而不是被拒绝,提高 [`store.connect_timeout_seconds`](/docs/zh-CN/claude-apps-gateway-config#store) 以给每个尝试更长的时间。 |414| 日志:`could not connect to Postgres at boot, attempt 1 of 3`,且原因不是 `remaining connection slots are reserved` | 网关启动时数据库尚无法访问,例如在网络仍在启动的冷实例上 | 如果网关随后完成启动,无需采取任何措施。当数据库无法访问时,网关在退出前尝试连接三次,间隔两秒。如果它以 `could not connect to Postgres` 退出,检查 `store.postgres_url`(包括它是否只指定了一个主机)以及到数据库的网络路径。如果尝试超时而不是被拒绝,提高 [`store.connect_timeout_seconds`](https://code.claude.com/docs/zh-CN/claude-apps-gateway-config#store) 以给每个尝试更长的时间。 |
401| 日志:`Postgres <version> is below the supported floor` | 数据库运行的 PostgreSQL 版本低于您的网关版本所支持的版本。网关会继续运行。 | 升级数据库。在 PostgreSQL 11、12 或 13 上,您也可以改为升级网关,以满足 [PostgreSQL 要求](/docs/zh-CN/claude-apps-gateway#prerequisites)。 |415| 日志:`Postgres <version> is below the supported floor` | 数据库运行的 PostgreSQL 版本低于您的网关版本所支持的版本。网关会继续运行。 | 升级数据库。在 PostgreSQL 11、12 或 13 上,您也可以改为升级网关,以满足 [PostgreSQL 要求](https://code.claude.com/docs/zh-CN/claude-apps-gateway#prerequisites)。 |
402| `/oauth/callback` 显示"Sign-in could not be completed" | 电子邮件域被拒绝、id\_token 验证失败,或 `email_verified` 显式为 `false`,网关总是拒绝且无覆盖 | 检查 `allowed_email_domains` 和 IdP 是否返回已验证的 `email` 声明。对于 `email_verified: false`,修复 IdP 端验证。如果您的 IdP 在不同的声明名称下发出电子邮件,设置 `oidc.email_claim`。 |416| `/oauth/callback` 显示"Sign-in could not be completed" | 电子邮件域被拒绝、id\_token 验证失败,或 `email_verified` 显式为 `false`,网关总是拒绝且无覆盖 | 检查 `allowed_email_domains` 和 IdP 是否返回已验证的 `email` 声明。对于 `email_verified: false`,修复 IdP 端验证。如果您的 IdP 在不同的声明名称下发出电子邮件,设置 `oidc.email_claim`。 |
403| 日志:`token exchange failed request_id=<id>: id_token missing email claim` | IdP 默认不在 id\_token 中包含 `email`。此拒绝仅在设置 `allowed_email_domains` 时触发;没有它,缺少的电子邮件会创建没有电子邮件的会话 | 配置 IdP 在 id\_token 中发出 `email`。Okta:将 `email` 添加到自定义授权服务器的 ID 令牌声明。Entra:在应用注册上添加 `email` 作为可选声明。PingFederate:启用发出 `email` 的 OpenID Connect 策略。如果 IdP 从 userinfo 端点提供 `email` 但不会在 id\_token 中包含它,例如 Okta 组织授权服务器,设置 `oidc.userinfo_fallback: true`。 |417| 日志:`token exchange failed request_id=<id>: id_token missing email claim` | IdP 默认不在 id\_token 中包含 `email`。此拒绝仅在设置 `allowed_email_domains` 时触发;没有它,缺少的电子邮件会创建没有电子邮件的会话 | 配置 IdP 在 id\_token 中发出 `email`。Okta:将 `email` 添加到自定义授权服务器的 ID 令牌声明。Entra:在应用注册上添加 `email` 作为可选声明。PingFederate:启用发出 `email` 的 OpenID Connect 策略。如果 IdP 从 userinfo 端点提供 `email` 但不会在 id\_token 中包含它,例如 Okta 组织授权服务器,设置 `oidc.userinfo_fallback: true`。 |
404| 日志:`refresh failed request_id=<id>: invalid_token (…) (at userinfo_no_id_token, …)`,开发者每 `session.ttl_hours` 看到 `Cloud gateway session expired` | IdP 接受了刷新令牌但没有随之返回 id\_token,所以网关询问了 IdP 的 userinfo 端点以获取用户的声明。IdP 在那里拒绝了刷新的访问令牌。网关回答 `temporarily_unavailable`,所以 Claude Code 保留刷新令牌但无法续订会话。v2.1.260 之前的网关版本记录相同的行但没有 `(at …)` 详情。 | 设置 [`oidc.scope_on_refresh: true`](/docs/zh-CN/claude-apps-gateway-config#oidc),在网关 v2.1.260 或更高版本中可用,以便刷新请求再次请求 `openid`。某些 IdP(如 Okta)仅在被要求时在刷新时返回 id\_token。在 PingFederate 上,改为在 **Applications > OAuth > OpenID Connect Policy Management** 下启用 **Return ID Token On Refresh Grant**。该设置项不会改变 PingFederate 的行为。对于仍然省略它的其他 IdP,检查 userinfo 端点是否接受由刷新发出的访问令牌。作为临时措施,提高 [`session.ttl_hours`](/docs/zh-CN/claude-apps-gateway-config#session)。请参阅[身份提供者设置](#identity-provider-setup)了解取消配置权衡。 |418| 日志:`refresh failed request_id=<id>: invalid_token (…) (at userinfo_no_id_token, …)`,开发者每 `session.ttl_hours` 看到 `Cloud gateway session expired` | IdP 接受了刷新令牌但没有随之返回 id\_token,所以网关询问了 IdP 的 userinfo 端点以获取用户的声明。IdP 在那里拒绝了刷新的访问令牌。网关回答 `temporarily_unavailable`,所以 Claude Code 保留刷新令牌但无法续订会话。v2.1.260 之前的网关版本记录相同的行但没有 `(at …)` 详情。 | 设置 [`oidc.scope_on_refresh: true`](https://code.claude.com/docs/zh-CN/claude-apps-gateway-config#oidc),在网关 v2.1.260 或更高版本中可用,以便刷新请求再次请求 `openid`。某些 IdP(如 Okta)仅在被要求时在刷新时返回 id\_token。在 PingFederate 上,改为在 **Applications > OAuth > OpenID Connect Policy Management** 下启用 **Return ID Token On Refresh Grant**。该设置项不会改变 PingFederate 的行为。对于仍然省略它的其他 IdP,检查 userinfo 端点是否接受由刷新发出的访问令牌。作为临时措施,提高 [`session.ttl_hours`](https://code.claude.com/docs/zh-CN/claude-apps-gateway-config#session)。请参阅[身份提供者设置](#identity-provider-setup)了解取消配置权衡。 |
405| 开发者登录后,来自该会话的每个请求都失败并返回 `431` 错误 | 每个请求的 `Authorization` 头中的会话令牌列出了开发者的 IdP 组,因此对于属于许多组的开发者,请求头总大小可能超过网关接受的上限 | 请参阅[登录后请求头过大](#request-headers-too-large-after-sign-in),了解适用哪个限制以及需要更改什么 |419| 开发者登录后,来自该会话的每个请求都失败并返回 `431` 错误 | 每个请求的 `Authorization` 头中的会话令牌列出了开发者的 IdP 组,因此对于属于许多组的开发者,请求头总大小可能超过网关接受的上限 | 请参阅[登录后请求头过大](#request-headers-too-large-after-sign-in),了解适用哪个限制以及需要更改什么 |
406| 每个 Amazon Bedrock 请求都返回 502;日志显示 `Could not load credentials from any providers` | 在 EC2 上,IMDSv2 的默认跳数限制为 1,阻止了来自容器内的实例元数据请求。启动和 `/readyz` 仍然通过,因为 AWS SDK 在第一个请求时解析实例凭据,而不是在客户端构造时 | 使用 `aws ec2 modify-instance-metadata-options --instance-id <id> --http-put-response-hop-limit 2` 提高跳数限制,或在启动模板中设置它。更改适用于实例上的每个容器。在可用的地方优先使用 ECS 任务角色,它们从 ECS 容器凭据端点读取凭据并完全避免更改,或在专用网关实例上应用更改以限制暴露。 |420| 每个 Amazon Bedrock 请求都返回 502;日志显示 `Could not load credentials from any providers` | 在 EC2 上,IMDSv2 的默认跳数限制为 1,阻止了来自容器内的实例元数据请求。启动和 `/readyz` 仍然通过,因为 AWS SDK 在第一个请求时解析实例凭据,而不是在客户端构造时 | 使用 `aws ec2 modify-instance-metadata-options --instance-id <id> --http-put-response-hop-limit 2` 提高跳数限制,或在启动模板中设置它。更改适用于实例上的每个容器。在可用的地方优先使用 ECS 任务角色,它们从 ECS 容器凭据端点读取凭据并完全避免更改,或在专用网关实例上应用更改以限制暴露。 |
407| 在峰值负载下,响应开始缓慢或似乎挂起,或在上游健康时失败,显示 502 `all upstreams failed` | 副本打开的请求比它一次发送到上游的请求多,所以额外的请求在网关内等待。在 `provider: anthropic` 上游上,等待时间超过 `timeouts.upstream_ttfb_ms` 的请求放弃该上游,当没有后续上游提供服务时会产生 502。日志显示包含 `client requests are open` 的警告。 | 添加副本,或提高每个副本上的限制。请参阅[并发上游请求](#concurrent-upstream-requests)。 |421| 在峰值负载下,响应开始缓慢或似乎挂起,或在上游健康时失败,显示 502 `all upstreams failed` | 副本打开的请求比它一次发送到上游的请求多,所以额外的请求在网关内等待。在 `provider: anthropic` 上游上,等待时间超过 `timeouts.upstream_ttfb_ms` 的请求放弃该上游,当没有后续上游提供服务时会产生 502。日志显示包含 `client requests are open` 的警告。 | 添加副本,或提高每个副本上的限制。请参阅[并发上游请求](#concurrent-upstream-requests)。 |
414| 登录在 IdP 处完成但回调失败,Chrome 中出现 CSP 错误或 Safari 中出现"this sign-in link has expired" | IdP 通过 `response_mode=form_post` 返回了代码,它通过 POST 跨源自动提交到 `/oauth/callback`。Chrome 在严格 CSP 下阻止了这个;Safari 允许提交但回调仅读取查询字符串。 | 确保您的 IdP 遵守 `response_mode=query`,网关明确请求它以便回调是普通重定向 |428| 登录在 IdP 处完成但回调失败,Chrome 中出现 CSP 错误或 Safari 中出现"this sign-in link has expired" | IdP 通过 `response_mode=form_post` 返回了代码,它通过 POST 跨源自动提交到 `/oauth/callback`。Chrome 在严格 CSP 下阻止了这个;Safari 允许提交但回调仅读取查询字符串。 | 确保您的 IdP 遵守 `response_mode=query`,网关明确请求它以便回调是普通重定向 |
415| 登录在本地工作但在 ALB 后面失败 | `public_url` 仍然命名本地或内部 `http://` 来源,所以 IdP 获得了错误的 `redirect_uri` | 将 `listen.public_url` 设置为外部 `https://` 来源,并向 IdP 注册 `<public_url>/oauth/callback` |429| 登录在本地工作但在 ALB 后面失败 | `public_url` 仍然命名本地或内部 `http://` 来源,所以 IdP 获得了错误的 `redirect_uri` | 将 `listen.public_url` 设置为外部 `https://` 来源,并向 IdP 注册 `<public_url>/oauth/callback` |
416| 开发者重复看到信任提示 | TLS 证书按副本或按请求轮换 | 在入口处使用稳定的证书,或终止 TLS 一次并在内部通过普通 HTTP 运行副本 |430| 开发者重复看到信任提示 | TLS 证书按副本或按请求轮换 | 在入口处使用稳定的证书,或终止 TLS 一次并在内部通过普通 HTTP 运行副本 |
417| CLI `/login`:"Could not verify the gateway's TLS certificate"或 `SELF_SIGNED_CERT_IN_CHAIN` | 网关的 TLS 链由 CLI 主机的信任存储中不存在的私有 CA 签名 | Claude Code 在本地二进制以及 Node 22.15 或更高版本上默认读取 OS 信任存储;[`CLAUDE_CODE_CERT_STORE`](/docs/zh-CN/network-config#ca-certificate-store) 控制此行为。如果 CA 安装在 OS 信任存储中,确保开发者使用当前运行时。否则在启动前将 `NODE_EXTRA_CA_CERTS` 设置为 CA 证书 PEM。首次连接指纹提示仍然适用。 |431| CLI `/login`:"Could not verify the gateway's TLS certificate"或 `SELF_SIGNED_CERT_IN_CHAIN` | 网关的 TLS 链由 CLI 主机的信任存储中不存在的私有 CA 签名 | Claude Code 在本地二进制以及 Node 22.15 或更高版本上默认读取 OS 信任存储;[`CLAUDE_CODE_CERT_STORE`](https://code.claude.com/docs/zh-CN/network-config#ca-certificate-store) 控制此行为。如果 CA 安装在 OS 信任存储中,确保开发者使用当前运行时。否则在启动前将 `NODE_EXTRA_CA_CERTS` 设置为 CA 证书 PEM。首次连接指纹提示仍然适用。 |
418| CLI `/login` 完成浏览器登录,然后会话以 `Cloud gateway sign-in was not completed` 和 TLS 证书不匹配结束 | 在登录后的第一个请求中,网关提供了与 Claude Code 固定的指纹不匹配的证书,所以 Claude Code 没有保留任何网关凭据。常见原因是一个地址后面的副本提供不同的证书,或网络路径上的某个东西拦截了 TLS。 | 为主机名提供一个证书,例如在入口处终止 TLS 一次,然后让开发者再次运行 `/login`。如果该证书与固定的不同,Claude Code 会在[信任提示](/docs/zh-CN/claude-apps-gateway#connect-developers)处显示警告,说明证书已更改。 |432| CLI `/login` 完成浏览器登录,然后会话以 `Cloud gateway sign-in was not completed` 和 TLS 证书不匹配结束 | 在登录后的第一个请求中,网关提供了与 Claude Code 固定的指纹不匹配的证书,所以 Claude Code 没有保留任何网关凭据。常见原因是一个地址后面的副本提供不同的证书,或网络路径上的某个东西拦截了 TLS。 | 为主机名提供一个证书,例如在入口处终止 TLS 一次,然后让开发者再次运行 `/login`。如果该证书与固定的不同,Claude Code 会在[信任提示](https://code.claude.com/docs/zh-CN/claude-apps-gateway#connect-developers)处显示警告,说明证书已更改。 |
419| CLI `/login` 停止,显示 `The gateway's TLS certificate changed during sign-in: it no longer matches the one you trusted` | 登录请求到达了一个证书与开发者在 `/login` 启动时接受的证书不匹配的服务器:一个地址后面的副本提供不同的证书、路径上的 TLS 拦截,或登录进行中的证书轮换。 | 为主机名提供一个证书,然后让开发者再次启动登录并在[信任提示](/docs/zh-CN/claude-apps-gateway#connect-developers)处审查新证书。 |433| CLI `/login` 停止,显示 `The gateway's TLS certificate changed during sign-in: it no longer matches the one you trusted` | 登录请求到达了一个证书与开发者在 `/login` 启动时接受的证书不匹配的服务器:一个地址后面的副本提供不同的证书、路径上的 TLS 拦截,或登录进行中的证书轮换。 | 为主机名提供一个证书,然后让开发者再次启动登录并在[信任提示](https://code.claude.com/docs/zh-CN/claude-apps-gateway#connect-developers)处审查新证书。 |
420 434
421`Cloud gateway sign-in was not completed` 消息会命名网关主机名。当 Claude Code 同时拥有固定指纹和呈现的指纹时,消息还显示每个的前 16 个字符。435`Cloud gateway sign-in was not completed` 消息会命名网关主机名。当 Claude Code 同时拥有固定指纹和呈现的指纹时,消息还显示每个的前 16 个字符。
422 436
426 440
427当开发者属于许多 IdP 组时,其请求可能在登录后失败并返回 `431` 错误。441当开发者属于许多 IdP 组时,其请求可能在登录后失败并返回 `431` 错误。
428 442
429当请求头总大小超过 256 KiB,或者在您设置了 [`limits.max_request_header_bytes`](/docs/zh-CN/claude-apps-gateway-config#http-tuning) 时超过该值,网关会返回 `431`。对于这些请求,网关不会写入任何日志行或审计事件。v2.1.284 之前的网关版本在超过 16 KiB 时返回 `431`。443当请求头总大小超过 256 KiB,或者在您设置了 [`limits.max_request_header_bytes`](https://code.claude.com/docs/zh-CN/claude-apps-gateway-config#http-tuning) 时超过该值,网关会返回 `431`。对于这些请求,网关不会写入任何日志行或审计事件。v2.1.284 之前的网关版本在超过 16 KiB 时返回 `431`。
430 444
431从以下各项中第一个适用于您网关的情况开始处理:445从以下各项中第一个适用于您网关的情况开始处理:
432 446
436 450
437精简组声明时,请保留您在以下设置中指定的组,这些设置决定开发者的访问权限、策略和支出上限:451精简组声明时,请保留您在以下设置中指定的组,这些设置决定开发者的访问权限、策略和支出上限:
438 452
439* **[`oidc.allowed_groups`](/docs/zh-CN/claude-apps-gateway-config#oidc)**:决定谁可以登录453* **[`oidc.allowed_groups`](https://code.claude.com/docs/zh-CN/claude-apps-gateway-config#oidc)**:决定谁可以登录
440* **[`admin.admin_groups`](/docs/zh-CN/claude-apps-gateway-config#admin)**:决定谁可以使用其网关会话调用管理 API454* **[`admin.admin_groups`](https://code.claude.com/docs/zh-CN/claude-apps-gateway-config#admin)**:决定谁可以使用其网关会话调用管理 API
441* **[`managed.policies`](/docs/zh-CN/claude-apps-gateway-config#managed) 中的 `match.groups`**:决定哪个策略适用于开发者455* **[`managed.policies`](https://code.claude.com/docs/zh-CN/claude-apps-gateway-config#managed) 中的 `match.groups`**:决定哪个策略适用于开发者
442* **`rbac_group` [支出上限](/docs/zh-CN/claude-apps-gateway-spend-limits.md)**:决定哪些组上限适用于开发者456* **`rbac_group` [支出上限](https://code.claude.com/docs/zh-CN/claude-apps-gateway-spend-limits.md)**:决定哪些组上限适用于开发者
443 457
444### 长时间思考导致代理超时458### 长时间思考导致代理超时
445 459
446如果您的上游是 `provider: anthropic`,请改用 [Anthropic API 上游上的长时间思考](#long-thinking-on-an-anthropic-api-upstream):在那里您同样需要提高 `CLAUDE_STREAM_IDLE_TIMEOUT_MS`,但时间和错误有所不同。460如果您的上游是 `provider: anthropic`,请改用 [Anthropic API 上游上的长时间思考](#long-thinking-on-an-anthropic-api-upstream):在那里您同样需要提高 `CLAUDE_STREAM_IDLE_TIMEOUT_MS`,但时间和错误有所不同。
447 461
448如果轮次在长时间思考后失败,且您的代理记录了一个保持打开约 12.5 分钟的请求,随后是一连串 `504` 错误,请在网关策略中提高 [`CLAUDE_STREAM_IDLE_TIMEOUT_MS`](/docs/zh-CN/env-vars)。例如,如果代理的空闲超时时间为 240 秒,这一连串错误就是 10 个请求,每个都在 240 秒时被切断。462如果轮次在长时间思考后失败,且您的代理记录了一个保持打开约 12.5 分钟的请求,随后是一连串 `504` 错误,请在网关策略中提高 [`CLAUDE_STREAM_IDLE_TIMEOUT_MS`](https://code.claude.com/docs/zh-CN/env-vars)。例如,如果代理的空闲超时时间为 240 秒,这一连串错误就是 10 个请求,每个都在 240 秒时被切断。
449 463
450* **第一个请求**:一个流,它传送首个响应事件 `message_start`,然后在 Claude 思考期间仅发送 ping。在默认设置下,Claude Code 会在约 12.5 分钟后结束该流。464* **第一个请求**:一个流,它传送首个响应事件 `message_start`,然后在 Claude 思考期间仅发送 ping。在默认设置下,Claude Code 会在约 12.5 分钟后结束该流。
451* **其余 10 个**:同一个请求,以[非流式方式](/docs/zh-CN/errors.md#streaming-response-ended-before-any-complete-data-was-received)发送并随后重试,默认总共发送 10 次。它们不会收到 ping,因此较慢的回复会触发代理的超时。465* **其余 10 个**:同一个请求,以[非流式方式](https://code.claude.com/docs/zh-CN/errors.md#streaming-response-ended-before-any-complete-data-was-received)发送并随后重试,默认总共发送 10 次。它们不会收到 ping,因此较慢的回复会触发代理的超时。
452 466
453此修复不需要更长的代理超时时间。如果您只提高代理的超时时间,一旦回复所需时间超过 Claude Code 自身的等待时间(默认 300 秒),非流式请求仍会失败。467此修复不需要更长的代理超时时间。如果您只提高代理的超时时间,一旦回复所需时间超过 Claude Code 自身的等待时间(默认 300 秒),非流式请求仍会失败。
454 468
460Error streaming, falling back to non-streaming mode: Stream idle timeout - no chunks received474Error streaming, falling back to non-streaming mode: Stream idle timeout - no chunks received
461```475```
462 476
463如果您的开发者已将 [`CLAUDE_CODE_DISABLE_NONSTREAMING_FALLBACK`](/docs/zh-CN/env-vars) 设置为 `1`,您不会看到任何非流式请求,该轮次会以 `API Error: Stream idle timeout - no chunks received` 结束。同样的修复方法适用。477如果您的开发者已将 [`CLAUDE_CODE_DISABLE_NONSTREAMING_FALLBACK`](https://code.claude.com/docs/zh-CN/env-vars) 设置为 `1`,您不会看到任何非流式请求,该轮次会以 `API Error: Stream idle timeout - no chunks received` 结束。同样的修复方法适用。
464 478
465#### 选择值479#### 选择值
466 480
472| `900000` | 约 22.5 分钟 |486| `900000` | 约 22.5 分钟 |
473| `1800000` | 约 37.5 分钟 |487| `1800000` | 约 37.5 分钟 |
474 488
475如果上游挂起而网关持续发送 ping,您的开发者也需要等待同样长的时间,Claude Code 才会放弃该流。完全静默的连接仍会在 5 到 6 分钟后结束,因为[响应体空闲超时](/docs/zh-CN/network-config.md#streaming-idle-watchdogs)不受此变量影响。489如果上游挂起而网关持续发送 ping,您的开发者也需要等待同样长的时间,Claude Code 才会放弃该流。完全静默的连接仍会在 5 到 6 分钟后结束,因为[响应体空闲超时](https://code.claude.com/docs/zh-CN/network-config.md#streaming-idle-watchdogs)不受此变量影响。
476 490
477#### 通过策略下发该值491#### 通过策略下发该值
478 492
479在 `gateway.yaml` 中,将 `env` 条目添加到已向您要覆盖的开发者下发 Claude Code 设置的每个策略中。将其放在该策略已有的 `code`、`cli` 或 `settings` 键下。如需先试用该值,可以从匹配单个组的策略开始。有关策略如何匹配和继承,请参阅 [`managed`](/docs/zh-CN/claude-apps-gateway-config#managed)。以下示例将该条目添加到键为 `cli` 的 `match: {}` 策略中:493在 `gateway.yaml` 中,将 `env` 条目添加到已向您要覆盖的开发者下发 Claude Code 设置的每个策略中。将其放在该策略已有的 `code`、`cli` 或 `settings` 键下。如需先试用该值,可以从匹配单个组的策略开始。有关策略如何匹配和继承,请参阅 [`managed`](https://code.claude.com/docs/zh-CN/claude-apps-gateway-config#managed)。以下示例将该条目添加到键为 `cli` 的 `match: {}` 策略中:
480 494
481```yaml theme={null}495```yaml theme={null}
482managed:496managed:
487 CLAUDE_STREAM_IDLE_TIMEOUT_MS: "1800000"501 CLAUDE_STREAM_IDLE_TIMEOUT_MS: "1800000"
488```502```
489 503
490使用 `cli` 键时,您可以覆盖终端、IDE 扩展和 Agent SDK 会话。对于 Claude Desktop 的 Code 标签页,请参阅[选择 `cli` 或 `code`](/docs/zh-CN/claude-apps-gateway-config#choose-cli-or-code)。504使用 `cli` 键时,您可以覆盖终端、IDE 扩展和 Agent SDK 会话。对于 Claude Desktop 的 Code 标签页,请参阅[选择 `cli` 或 `code`](https://code.claude.com/docs/zh-CN/claude-apps-gateway-config#choose-cli-or-code)。
491 505
492重启网关,使其读取编辑后的文件。然后让开发者重启 Claude Code 以获取 `CLAUDE_STREAM_IDLE_TIMEOUT_MS`。506重启网关,使其读取编辑后的文件。然后让开发者重启 Claude Code 以获取 `CLAUDE_STREAM_IDLE_TIMEOUT_MS`。
493 507
494### Anthropic API 上游上的长时间思考508### Anthropic API 上游上的长时间思考
495 509
496如果 `provider: anthropic` 是该模型唯一的上游,且您的代理记录了一个保持打开约 20 分钟的请求,随后是 `502` 或 `504` 错误,请在网关策略中提高 [`CLAUDE_STREAM_IDLE_TIMEOUT_MS`](/docs/zh-CN/env-vars)。510如果 `provider: anthropic` 是该模型唯一的上游,且您的代理记录了一个保持打开约 20 分钟的请求,随后是 `502` 或 `504` 错误,请在网关策略中提高 [`CLAUDE_STREAM_IDLE_TIMEOUT_MS`](https://code.claude.com/docs/zh-CN/env-vars)。
497 511
498* **长时间请求**:一个流,它传送 `message_start`,然后在 Claude 思考期间仅发送 ping。在默认设置下,Claude Code 会在约 20 分钟后结束它;提高该变量后,结束时间会相应推迟。512* **长时间请求**:一个流,它传送 `message_start`,然后在 Claude 思考期间仅发送 ping。在默认设置下,Claude Code 会在约 20 分钟后结束它;提高该变量后,结束时间会相应推迟。
499* **错误**:Claude Code 随后以[非流式方式](/docs/zh-CN/errors.md#streaming-response-ended-before-any-complete-data-was-received)发送的请求。每个请求都会因网关返回的 `502` 而失败;如果代理的超时时间短于网关的等待时间,则会因代理的 `504` 而失败。该等待时间即 [`timeouts.upstream_ttfb_ms`](/docs/zh-CN/claude-apps-gateway-config#http-tuning),此修复无需提高它。513* **错误**:Claude Code 随后以[非流式方式](https://code.claude.com/docs/zh-CN/errors.md#streaming-response-ended-before-any-complete-data-was-received)发送的请求。每个请求都会因网关返回的 `502` 而失败;如果代理的超时时间短于网关的等待时间,则会因代理的 `504` 而失败。该等待时间即 [`timeouts.upstream_ttfb_ms`](https://code.claude.com/docs/zh-CN/claude-apps-gateway-config#http-tuning),此修复无需提高它。
500 514
501要确认原因,请参阅[确认原因](#confirm-the-cause)。515要确认原因,请参阅[确认原因](#confirm-the-cause)。
502 516
504 518
505## 相关519## 相关
506 520
507* [Claude 应用网关概述](/docs/zh-CN/claude-apps-gateway):快速入门和开发者连接521* [Claude 应用网关概述](https://code.claude.com/docs/zh-CN/claude-apps-gateway):快速入门和开发者连接
508* [配置参考](/docs/zh-CN/claude-apps-gateway-config.md):每个 `gateway.yaml` 选项522* [配置参考](https://code.claude.com/docs/zh-CN/claude-apps-gateway-config.md):每个 `gateway.yaml` 选项