Planifica primero la red de tu gateway. Al iniciar sesión, Claude Code rechaza un Claude apps gateway cuyo nombre de host se resuelve en una dirección IP pública, incluso una a la que no se puede acceder desde internet.Un Claude apps gateway puede enviar configuración a las máquinas de los usuarios, incluidos hooks que ejecutan comandos de shell. Esta comprobación ayuda a evitar que los usuarios inicien sesión por accidente en un gateway malicioso en internet pública. Mantén también tu propio gateway fuera de internet.Elige la dirección del gateway antes de elegir dónde se ejecuta. Por lo general, es una dirección privada a la que los usuarios acceden desde tu red interna o a través de una VPN. Si tu red interna usa rangos IPv4 públicos, puedes indicar un rango que contenga tanto el gateway como las máquinas de tus usuarios. Claude Code toma esa coincidencia como señal de que el gateway está en tu red interna. Consulta Elegir una dirección para el gateway. Si ninguna de las dos opciones se ajusta a tu red, comunícate con tu equipo de cuenta de Anthropic.
gateway.yaml que la puerta de enlace lee al iniciar, consulte la referencia de configuración.
Una implementación de producción sigue cuatro pasos en orden, y las secciones a continuación coinciden con ellos. Los dos primeros son donde usted toma decisiones; los dos segundos son material de referencia para consultar una vez que esté en funcionamiento.
- Configurar su proveedor de identidad: registre el cliente OAuth y verifique las notas específicas de cada IdP para Okta, Entra y Google
- Implementar la puerta de enlace: construya una imagen de contenedor fijada y ejecútela en Kubernetes, Cloud Run o su propia plataforma. Esta sección también cubre decisiones sobre costo, omisión, múltiples puertas de enlace y sin servidor
- Configurar operaciones: registros, sondeos de salud, comportamiento de interrupciones, rotación de secretos y actualizaciones. Referencia para cuando esté conectando monitoreo y runbooks
- Revisar la postura de seguridad: qué datos fluyen hacia dónde, el modelo de amenaza y respuestas de cumplimiento. Referencia para una revisión de seguridad
Configuración del proveedor de identidad
Registra una aplicación web confidencial de OAuth/OpenID Connect (OIDC) con un único URI de redirección,https://<gateway>/oauth/callback, y asígnala a los usuarios o grupos que deben tener acceso al gateway. El gateway se autentica ante el IdP con el secreto de cliente del registro, o con un certificado que subes al registro si tu IdP usa credenciales de certificado en su lugar.
Cualquier IdP compatible con OIDC funciona: Okta, Microsoft Entra ID, Google Workspace, Keycloak, Dex, PingFederate y otros. El IdP debe cumplir tres requisitos:
- Sirve
/.well-known/openid-configuration, sobre HTTPS en producción; la puerta de enlace acepta un emisorhttp://, y un emisor de loopback además requiereCLAUDE_GATEWAY_ALLOW_LOOPBACK=1 - Admite el flujo de código de autorización. PKCE (Proof Key for Code Exchange) está activado de forma predeterminada; desactívelo con
oidc.use_pkce: falsepara IdPs que no lo admitan - Devuelve
emaily opcionalmentegroupsen el id_token, o los sirve desde el punto final de userinfo conoidc.userinfo_fallback: true
oidc.ca_cert_pem.
Algunos proveedores manejan las reclamaciones de correo electrónico y grupo de manera diferente:
- Okta: el servidor de autorización de la organización en
https://example.okta.comdevuelve un id_token delgado que omiteemailygroups, así que establezcaoidc.userinfo_fallback: truesiempre que lo use comoissuer. Un servidor de autorización personalizado comohttps://example.okta.com/oauth2/defaultque incluyeemaily opcionalmentegroupsen el id_token los emite directamente y no necesita fallback. Okta emitegroupssolo cuando se solicita el alcancegroupsenoidc.scopesy el filtro de reclamación de grupos de la aplicación lo permite;userinfo_fallbackno puede llenar una reclamación que el IdP no fue solicitado. - Microsoft Entra ID:
issuer=https://login.microsoftonline.com/<tenant-id>/v2.0. Entra emite IDs de objeto de grupo en lugar de nombres, así que use los GUIDs enmanaged.policies.match.groups, o use App Roles para nombres legibles por humanos. Si su inquilino emite roles bajorolesen lugar degroups, establezcaoidc.groups_claim: roles. - Google Workspace:
issuer=https://accounts.google.com. El id_token de Google no lleva grupos. Para usarallowed_groupsbasado en grupos omanaged.policiescon Google como IdP, configureoidc.google_groups, que busca los grupos de cada usuario a través de la API de directorio del SDK de administración usando una cuenta de servicio con delegación en todo el dominio. Sin él, useoidc.allowed_email_domainspara control de membresía ymanaged.policies.match.email_domainpara asignación de políticas. Google también ignora el alcance estándaroffline_access. Para tokens de actualización, establezcaoidc.scopes: [openid, profile, email]yoidc.extra_auth_params: { access_type: offline, prompt: consent }.
Implementación
El gateway es un único binario de Linux sin estado que se coordina a través de Postgres, así que despliégalo de la misma manera en que despliegas cualquier otro servicio sin estado en tu entorno. Mantenlo dentro de tu red, donde tus desarrolladores puedan alcanzarlo a través de HTTPS y él pueda alcanzar tu IdP, y trátalo como cualquier servicio que contiene una credencial de producción. Algunas decisiones dan forma a la implementación más allá de dónde se ejecuta:- Costo: sin licencia separada ni tarifa por asiento. La puerta de enlace es parte del binario
claude, así que paga por inferencia a través de su compromiso existente, más el cálculo que ejecuta. - Derivación: la puerta de enlace no impone que la única ruta a un modelo pase por ella. Un desarrollador con su propia credencial aún puede llamar al proveedor directamente, así que cerrar ese camino es una decisión de política de red, por ejemplo bloqueando la salida a
api.anthropic.comexcepto desde la puerta de enlace. Bloquear esa salida también rompe la verificación de seguridad de dominio de WebFetch, que llama aapi.anthropic.comdesde la máquina de cada desarrollador. EstablezcaskipWebFetchPreflight: trueen la política administrada para deshabilitarlo. - Múltiples puertas de enlace: cada una es una implementación separada con su propia configuración, y el CLI almacena confianza y credenciales por nombre de host de puerta de enlace, así que los equipos pueden usar diferentes puertas de enlace sin conflicto. Para servir múltiples emisores OIDC, ejecute instancias separadas.
- Sin servidor: Cloud Run funciona si establece
min-instances: 1para evitar descubrimiento OIDC frío. Lambda y Cloud Functions no funcionan, porque la puerta de enlace es un servidor HTTP de larga duración.
listen.trusted_proxies en los rangos de origen del proxy para que la puerta de enlace lea las IPs del cliente desde X-Forwarded-For. La puerta de enlace honra el encabezado solo cuando el par TCP es confiable. Los ejemplos trabajados de Google Cloud y AWS tienen valores concretos por topología. Sin proxies confiables, cada solicitud parece provenir de la IP del proxy, lo que colapsa los límites de velocidad por IP en un cubo compartido y registra la IP del proxy en eventos de auditoría.
No redirija solicitudes a los puntos finales de autorización de dispositivo y token de la puerta de enlace, por ejemplo con una reescritura de HTTP a HTTPS o canonicalización de host en el ingress. Claude Code no sigue redirecciones en esas solicitudes, así que una regla de ingress que las redirija rompe el inicio de sesión y la actualización de token.
Dé al proxy cualquier tiempo de espera inactivo más largo que el intervalo de keepalive de la puerta de enlace, que depende del ascendente:
- En cada ascendente excepto
provider: anthropic, la puerta de enlace escribe unpingSSE una vez que una secuencia ha estado silenciosa durante aproximadamente 15 segundos. - En
provider: anthropic, la puerta de enlace pasa la respuesta sin cambios, incluidos los pings propios de la API de Anthropic.
Elige una dirección para el gateway
Claude Code acepta la dirección de un gateway de una de dos maneras:- Dirección privada: coloca el gateway detrás de un balanceador de carga interno o una VPN, con un nombre de host que se resuelva solo a direcciones privadas, como RFC 1918 o CGNAT
100.64.0.0/10. Las máquinas de los usuarios pueden estar en cualquier dirección. El requisito previo de red privada enumera los rangos aceptados. - Bloque declarado: si tu red interna usa espacio IPv4 público que pertenece a tu organización, enumera el bloque en el ajuste de configuración administrada
gatewayInternalNetworks. Tanto el gateway como la máquina del usuario deben estar en ese bloque. Consulta Permitir un gateway en espacio de direcciones públicas de tu propiedad.
Imagen de contenedor
Construya su propia imagen alrededor del binario nativoclaude de la versión estándar de Claude Code:
- Descargue la compilación de Linux para la arquitectura de su imagen desde una versión fija; consulte Instalar una versión específica para la URL de descarga.
- Verifíquelo contra el
manifest.jsonfirmado con GPG de la versión como se describe en Integridad binaria y firma de código. - Cópielo en el contexto de compilación.
- Una imagen basada en glibc: las únicas dependencias dinámicas de la compilación de glibc son bibliotecas de glibc. Las imágenes basadas en musl necesitan la compilación
linux-x64-muslolinux-arm64-musl, cuya única dependencia dinámica es musl. - Un directorio de estado escribible: la puerta de enlace se ejecuta como cualquier usuario, pero las imágenes mínimas no tienen inicio escribible. Establezca
CLAUDE_CONFIG_DIRen una ruta escribible como/tmp/.claude. - El comando del contenedor:
claude gateway --config /etc/claude/gateway.yaml, con el archivo de configuración montado de solo lectura y secretos suministrados como variables de entorno; la puerta de enlace escucha enlisten.port, predeterminado8080.
Kubernetes
Ejecute la puerta de enlace como una Deployment, como cualquier servicio sin estado:- Monte la configuración desde un ConfigMap y secretos desde un Secret; haga referencia a secretos en el YAML a través de
${file:/path/to/secret}o como variables de entorno - Termine TLS en el Ingress y establezca
listen.public_urlen el nombre de host de Ingress - Apunte la sonda de preparación a
GET /readyzy la sonda de vivacidad aGET /healthz
upstreams tiene detalles de configuración por plataforma. Para un emparejamiento entre nubes, como un ascendente de Bedrock en GKE, establezca credenciales explícitas en el bloque auth del ascendente en su lugar.
Cloud Run
Configure el servicio de la siguiente manera:- Deje
listen.porten su predeterminado de8080, que coincide con elPORTpredeterminado de Cloud Run, o establezcaport: ${PORT} - Establezca
public_urlen el origen externamente alcanzable. Para producción esto es normalmente el nombre de host de un equilibrador de carga interno, porque/loginrechaza direcciones públicas y la URL*.run.appse resuelve a una, así que la URL de Cloud Run sola funciona solo para una prueba de humocurlo navegador. La excepción es una red donde*.run.appse resuelve privadamente a través de Private Service Connect y una zona privada de Cloud DNS; en esa topología la URL de Cloud Run es unpublic_urlválido. El ejemplo trabajado de Google Cloud cubre ambos. - Monte la configuración como un volumen secreto
- Establezca
min-instances: 1para evitar un descubrimiento OIDC frío en la primera solicitud
Enviar la URL de la puerta de enlace a máquinas de desarrolladores
Una vez que el gateway esté en servicio, envíaforceLoginMethod, forceLoginGatewayUrl y parentSettingsBehavior: "merge" a la máquina de cada desarrollador a través de la configuración administrada, mediante MDM o escribiendo directamente el managed-settings.json correspondiente a cada sistema operativo.
Una vez que implemente las claves, Claude Code deja de usar una clave API sobrante o un inicio de sesión de claude.ai en la máquina, así que planifique el envío junto con sus instrucciones de inicio de sesión. La política del administrador requiere un inicio de sesión de puerta de enlace en la nube describe los mensajes que ven los desarrolladores.
Consulte dónde cada mecanismo almacena la política para las rutas de archivo, y Configuraciones administradas del lado del cliente para el equivalente de bootstrapUrl de Claude Desktop.
Implementaciones a gran escala
El inicio de sesión tiene límite de velocidad por dirección IP del cliente, y los valores predeterminados se adaptan a un equipo pequeño. Cada dirección obtiene 30 inicios de sesión y 10 envíos de código cada 10 minutos. Una implementación para miles de desarrolladores puede alcanzar esos límites en la primera mañana, por una de dos razones:- El gateway no puede ver más allá de tu balanceador de carga. Sin
listen.trusted_proxies, todos los desarrolladores parecen provenir de la dirección del balanceador de carga y comparten un único límite. El gateway registra una advertencia la primera vez que ignora un encabezadoX-Forwarded-For. Si el balanceador de carga debe figurar enlisten.trusted_proxies, agrégalo antes de cambiar cualquier otra cosa. Si los desarrolladores siguen compartiendo una única dirección, aumentarate_limits. - Muchos desarrolladores comparten pocas direcciones de salida NAT o VPN. Comparten los límites de esas direcciones incluso cuando
trusted_proxieses correcto. Aumenterate_limitspara ajustarse.
max, divida los desarrolladores por las direcciones de salida que comparten. Estime cuántos de ellos inician sesión dentro de un período window_seconds, que es 10 minutos de forma predeterminada. Luego duplíquelo para cubrir reintentos y desarrolladores que inician sesión tanto en Claude Code como en Claude Desktop.
Por ejemplo, 10.000 desarrolladores detrás de 4 direcciones de salida inician sesión uniformemente durante una hora. Eso es 2.500 desarrolladores por dirección y aproximadamente 420 de ellos en cada 10 minutos, que duplica y redondea hasta 1.000. El ejemplo a continuación establece ambos límites en 1.000:
device_verify es lo que impide que alguien adivine el código de inicio de sesión de otro desarrollador, así que auméntelo solo en la medida que su estimación necesite. Incluso en estos límites, un código tiene 8 caracteres de un alfabeto de 20 caracteres y expira después de 10 minutos, así que adivinar sigue siendo impracticable; consulte Resistencia a fuerza bruta de código de usuario.
Cuando su IdP emite tokens de actualización, Claude Code renueva sesiones silenciosamente, así que puede volver a poner el límite después de la implementación. Sin tokens de actualización, los desarrolladores inician sesión nuevamente cada session.ttl_hours. Dimensione ambos límites para esa velocidad constante también y déjelos elevados.
Cuando se alcanza un límite, Claude Code v2.1.274 o posterior muestra The gateway is limiting sign-in attempts right now. Una puerta de enlace en v2.1.274 o posterior muestra Too many attempts came from your network address en la página de verificación, con la configuración a verificar. También escribe una línea de registro sign-in refused que nombra la configuración a cambiar.
Operaciones
Una vez que la puerta de enlace está sirviendo tráfico, la operación día a día es leer sus registros, sondear su salud y rotar sus secretos en su horario. Las subsecciones cubren cada una, más lo que Postgres contiene y cómo se comportan las actualizaciones y reversiones.Registros
La puerta de enlace escribe dos flujos a stderr, ambos amigables con JSON:-
Audit events: JSON de una sola línea por evento relevante para la seguridad. Canalice stderr a su agregador de registros.
Los eventos emitidos incluyen
config.load,session.mint,session.refresh,device.authorize,device.verify,device.callback,auth.denied,access.denied,access.public_client,inference,managed.serve,desktop_bootstrap.serve,desktop_bootstrap.denied,spend.blocked,admin.denied,admin.limit.upsertyadmin.limit.delete. Los campos varían según el evento:- Los eventos de emisión y actualización exitosos incluyen
sub,email,client_ipy el resultado auth.deniedyaccess.deniedincluyen el motivo y la IP del cliente, además de la ruta de la solicitud en el caso deauth.denied, ya que en esas denegaciones no existe identidad de usuario. Dos motivos deaccess.deniedcambian lo que incluye el evento:xff_unparseable: el evento también incluye la entrada deX-Forwarded-Forque no se pudo leerclient_ip_unknown: el evento no incluye IP del cliente, porque la conexión no tenía dirección del par mientras había una lista deaccess_controlconfigurada
access.public_clientincluye la IP del cliente de la primera solicitud por proceso que llega desde una dirección pública mientrasaccess_control.allow_cidrsestá vacío. El gateway atiende la solicitud como de costumbre; el evento indica que el gateway puede ser accesible desde internet pública. Consulta la referencia deaccess_controlpara saber qué cuenta como público y cuál es la lista de permitidos recomendada.inferenceregistra qué upstream atendió la solicitud y el estado de la respuestadesktop_bootstrap.deniedregistra una obtención de arranque de Claude Desktop rechazada, con el motivo (not_configured,policy_not_opted_inono_policy_matched) y la identidad del usuarioguardrail.traceregistra qué filtro se activó, sin el texto coincidenteadmin.deniedregistra un intento de autenticación rechazado en la API de administración con la IP del cliente, el método, la ruta y un motivo, sin el material de clave presentado:invalid_keycuando se presentó unax-api-keyque no coincidió con ninguna clave configurada,bearer_rejectedcuando solo se presentó un encabezadoAuthorizationy no se verificó como una sesión del gateway enadmin.admin_groups, ono_credentialscuando no se presentó ninguno de los dos encabezados
- Los eventos de emisión y actualización exitosos incluyen
-
Registros operacionales: líneas legibles por humanos con prefijo
[gateway]para arranque, advertencias y errores ascendentes. La variable de entornoCLAUDE_GATEWAY_LOG_LEVELcontrola la verbosidad y aceptadebug,info,warnoerror, coninfocomo predeterminado. Endebug, cada inicio de sesión y actualización también registra los nombres, no los valores, de los reclamos en el id_token, más los nombres de los reclamos de userinfo cuandouserinfo_fallbackproporcionó alguno, para que pueda diagnosticar la configuración deemail_claimygroups_claimsin registrar PII. No afecta los eventos de auditoría, que siempre se emiten.
Escribe los registros operativos como JSON
Si tu recolector de registros lee el nivel de cada línea desde un campo JSON, estableceCLAUDE_GATEWAY_LOG_FORMAT=json en el entorno del gateway. Requiere Claude Code v2.1.319 o posterior en el servidor del gateway.
Cada línea del registro operativo pasa a ser un objeto con severity, time y message:
severity es el nivel de registro en mayúsculas, con warn escrito como WARNING. Un arranque fallido es una línea ERROR.
Los eventos de auditoría, que también van a stderr, no cambian. Incluyen ts y evt, y no severity.
Salud
La puerta de enlace sirveGET /healthz como una sonda de vivacidad y GET /readyz como una sonda de preparación. /readyz verifica que el almacén sea alcanzable. Si establece store.readiness_grace_seconds, /readyz sigue reportando listo durante hasta esa cantidad de segundos después de que el almacén deja de responder.
Ambos extremos están exentos de access_control.allow_cidrs, así que los sondeos siguen funcionando en un oyente bloqueado.
El documento de descubrimiento de OAuth en /.well-known/oauth-authorization-server también devuelve 200 solo después de que se cargue la configuración, descubrimiento OIDC, construcción de cliente ascendente y migración de Postgres tengan éxito, así que funciona como una verificación de arranque de extremo a extremo.
Solicitudes ascendentes concurrentes
De forma predeterminada, cada réplica de puerta de enlace envía como máximo 256 solicitudes ascendentes al mismo tiempo. Una respuesta de transmisión cuenta contra el límite hasta que la transmisión termina. Una solicitud que llega mientras una réplica está en el límite espera dentro de la puerta de enlace por un espacio libre. El desarrollador ve una respuesta que es lenta para comenzar o parece colgarse. En una puerta de enlace ascendenteprovider: anthropic, una solicitud que espera más tiempo que timeouts.upstream_ttfb_ms se rinde en esa puerta de enlace ascendente, y falla con un 502 cuando ninguna puerta de enlace ascendente posterior la sirve.
La línea de registro de inicio que contiene upstream requests: muestra el límite en vigor. Mientras una réplica tiene más solicitudes abiertas que el límite, también registra una advertencia que contiene client requests are open, como máximo una vez por minuto.
Para servir más solicitudes a la vez, tiene dos opciones:
- Agregue réplicas.
- Aumente el límite en cada réplica. Establezca la variable de entorno
BUN_CONFIG_MAX_HTTP_REQUESTSen el contenedor de puerta de enlace en un número entero de 1 a 65535, luego reinicie el contenedor.
client requests are open.
En una prueba de carga con load_test_mode, las solicitudes no esperan en este límite, pero una réplica igualmente registra la advertencia client requests are open.
Mantén API_TIMEOUT_MS por encima del tiempo hasta el primer byte del gateway
Si reduces API_TIMEOUT_MS para reintentar antes una solicitud sin respuesta, mantenlo por encima del tiempo que tarda el gateway en enviar los primeros bytes de una respuesta en streaming. Una solicitud que espera más agota su tiempo de espera, y lo mismo ocurre con cada reintento que espera lo mismo, hasta que el turno termina con Request timed out, a menos que el plazo del primer byte lo termine antes.
provider: anthropic: estableceAPI_TIMEOUT_MSpor encima del tiempo máximo que tarda tu upstream en enviar su primer evento.- Cualquier otro upstream: establécelo más de 20 segundos por encima del tiempo máximo que tarda tu upstream en devolver los encabezados de respuesta. El gateway envía su primer
pingde keepalive unos 15 segundos después de esos encabezados, a menos que el primer evento del upstream llegue antes. Un gateway anterior a v2.1.229 no envía pings, así que en ese caso usa la regla deprovider: anthropic.
Reintenta antes una solicitud sin respuesta con el plazo del primer byte
Para que Claude Code reintente antes una solicitud en streaming sin respuesta, dale un plazo del primer byte configurandoCLAUDE_STREAM_FIRST_BYTE_TIMEOUT_MS en las máquinas de tus desarrolladores. El plazo limita cuánto espera el primer intento a los encabezados de respuesta. Sin él, ese intento puede esperar de 5 a 6 minutos. Requiere Claude Code v2.1.307 o posterior en la máquina del desarrollador.
Establece la variable en un número entero positivo de milisegundos, en el bloque env de una política del gateway o en el shell de un desarrollador. Mantén el valor por encima del tiempo hasta el primer byte más largo de tu gateway, o Claude Code puede abortar y reenviar solicitudes sanas cuyos encabezados tardan más. Este ejemplo establece 60 segundos en el shell de un desarrollador:
API_TIMEOUT_MS solo para reintentar antes, elimina ese valor, o un reenvío sin respuesta puede terminar el turno con No response from API.
Para confirmar que el plazo se activó, pide a un desarrollador que inicie Claude Code con el registro de depuración y luego busca [first-byte] no response headers en el registro.
Comportamiento de interrupciones
Si Postgres se cae, la puerta de enlace en sí sigue sirviendo desarrolladores con sesión iniciada y los nuevos inicios de sesión fallan. Si los desarrolladores realmente siguen trabajando depende de cómo su orquestador maneja la preparación:- Sesiones existentes: los tokens portadores se validan localmente con el secreto JWT, las actualizaciones de sesión no tocan el almacén, y el proceso de puerta de enlace aún puede servir inferencia
- Nuevos inicios de sesión: fallan hasta que Postgres se recupere, porque el flujo de dispositivo y sus contadores de límite de velocidad viven en Postgres
- Cumplimiento de límite de gasto: falla abierto de forma predeterminada durante la interrupción, así que la inferencia aún fluye; cámbielo a falla cerrada si preferiría bloquear que ejecutar sin medidor
- Preparación: por defecto
/readyzreporta no listo tan pronto como Postgres sea inalcanzable, así que cada réplica falla su verificación de preparación a la vez. Donde el tráfico solo llega a réplicas que pasan la verificación, todo el tráfico, incluida la inferencia que la puerta de enlace podría servir, falla hasta que Postgres se recupere. La sonda de vivacidad en/healthzsigue pasando durante todo.
ttl_hours y los nuevos inicios de sesión fallan. Una actualización de sesión obtiene una respuesta de reintentar y funciona una vez que el IdP está de vuelta. Establezca un ttl_hours más largo si su IdP tiene ventanas de mantenimiento frecuentes.
Período de gracia de preparación
Para mantener a los desarrolladores con sesión iniciada trabajando a través de una interrupción corta de Postgres, como una conmutación por error de base de datos, establezcastore.readiness_grace_seconds a más tiempo que lo que tarda la conmutación por error, por ejemplo 300. Con límites de gasto activados y el comportamiento de falla abierta predeterminado, las solicitudes a través de una réplica que permanece lista no tienen medidor hasta que Postgres se recupere, así que mantenga el valor tan bajo como cubre su conmutación por error. Si establece enforcement.fail_closed_on_error: true, la puerta de enlace rechaza la inferencia de desarrolladores con sesión iniciada con el mensaje 429 spend limit unavailable hasta que Postgres se recupere, incluso mientras las réplicas aún pasan su verificación de preparación.
La configuración requiere Claude Code v2.1.282 o posterior en el servidor de puerta de enlace. Una puerta de enlace anterior se niega a iniciar cuando encuentra la clave, así que actualice cada réplica antes de agregarla. Upgrades cubre la reversión.
Si apunta la sonda de preparación a /healthz en su lugar, las réplicas también siguen pasándola a través de una interrupción, pero /healthz nunca reporta no listo, así que una réplica cuya conexión de Postgres no se recupera sigue pasando también.
Rotación de secreto JWT
Rote el secreto de firma en etapas para que las sesiones existentes permanezcan válidas:- Genere un nuevo secreto. Antepóngalo a la matriz
session.jwt_secret. - Despliegue la implementación. Los nuevos tokens firman con el nuevo secreto; los tokens antiguos aún se verifican.
- Después de
ttl_hoursmás un margen, elimine el secreto antiguo y despliegue nuevamente.
ttl_hours.
Postgres
El gateway guarda su estado en una base de datos PostgreSQL:- Base de datos: PostgreSQL propiamente dicho, autoalojado o administrado, en la versión mínima o posterior. No se admiten bases de datos que solo implementan el protocolo de Postgres, como las bases de datos SQL distribuidas.
- Dirección:
store.postgres_urlacepta un solo host. Si la base de datos tiene varios nodos, usa la dirección que está delante de ellos, como el endpoint de tu servicio administrado, un balanceador de carga o una IP virtual. Configura un período de gracia de disponibilidad más largo de lo que tarda una conmutación por error.
_migrations, todas creadas por sus migraciones de tiempo de arranque:
Un bucle de 30 segundos expira filas
kv pasadas su TTL, y un barrido cada hora impone las ventanas de retención en las tablas de gasto, así que nada crece sin límite. Sin límites de gasto configurados, solo se escribe kv. La puerta de enlace aplica sus propias migraciones de esquema al arrancar y en cada actualización, así que su rol de base de datos necesita derechos para crear y alterar tablas. Apúntelo a una base de datos o esquema dedicado a la puerta de enlace para mantener ese permiso estrecho.
Con límites de gasto en uso, una base de datos perdida significa pérdida de seguimiento de gasto y límites, no solo re-inicios de sesión de desarrolladores, así que ejecute copias de seguridad regulares. Para borrar un desarrollador que se fue inmediatamente en lugar de esperar en retención, ejecute DELETE FROM principal_emails WHERE principal = '<sub>' directamente; eso elimina la única tabla que contiene su correo electrónico, nombre y grupos. Las filas spend y admin_audit hacen referencia solo al sub OIDC seudónimo.
Dimensiona el pool de conexiones
Cada réplica abre hastastore.max_connections conexiones a Postgres, cinco de forma predeterminada. Mantén réplicas × store.max_connections igual o por debajo de las conexiones que la base de datos tiene disponibles para el gateway:
- Réplicas: cuenta el máximo que se ejecutan a la vez. Parte de tu máximo de autoescalado, o de tu número de réplicas si no usas autoescalado, y suma las réplicas adicionales que una actualización gradual inicia antes de detener las antiguas. En Amazon ECS con la configuración predeterminada, y en Cloud Run, pueden ser otras tantas.
- Conexiones disponibles: toma el
max_connectionsde la base de datos y resta lo que la base de datos reserva y lo que ocupan otros clientes. PostgreSQL reservasuperuser_reserved_connections, tres de forma predeterminada. Un servicio administrado puede reservar más, así que consulta su documentación.
max_connections de 50 y dos conexiones ocupadas por otros clientes tiene 50 − 3 − 2 = 45 disponibles, así que el total cabe.
Si tu total no cabe, cambia uno de estos elementos:
- La base de datos: aumenta su
max_connections - Las réplicas: ejecuta menos, o haz que tu orquestador inicie menos réplicas adicionales en una actualización gradual
- El pool: reduce
store.max_connections, pero con los límites de gasto activados, mantenlo lo bastante grande para la carga de cada réplica. De lo contrario, las verificaciones de gasto pueden agotar su tiempo de espera esperando una conexión, y el gateway registraspend check failed: spend precheck timed out.
Actualizaciones
Las réplicas son sin estado, así que un reinicio rodante no pierde ningún estado de puerta de enlace. La puerta de enlace ejecuta migraciones de esquema al arrancar, lo que significa que implementar el nuevo binario auto-migra la base de datos. Las réplicas concurrentes se serializan en un bloqueo de asesor de Postgres, así que solo una aplica cada migración. Cuando su orquestador detiene una réplica conSIGTERM, como en un reinicio rodante o una reducción de escala, la puerta de enlace deja de aceptar nuevas conexiones y permite que las solicitudes y transmisiones ya en vuelo terminen antes de salir. Espera hasta 25 segundos, llamado la ventana de drenaje, luego cierra lo que aún esté abierto. Un SIGINT, como Ctrl+C en una terminal, inicia el mismo drenaje, y una segunda señal durante el drenaje cierra las solicitudes abiertas y sale de inmediato. El drenaje requiere puerta de enlace v2.1.274 o posterior.
Las generaciones largas pueden transmitir durante minutos. En Kubernetes y Amazon ECS, aumente ambos de estos juntos para dar a esas transmisiones más tiempo:
- La ventana de drenaje: establezca la variable de entorno
CLAUDE_GATEWAY_DRAIN_TIMEOUT_MSen el contenedor de puerta de enlace en un número entero positivo de milisegundos, como120000. La puerta de enlace ignora un valor en cualquier otra forma, como120s, y mantiene el predeterminado de 25 segundos - El período de gracia de su orquestador:
terminationGracePeriodSecondsen Kubernetes, ostopTimeouten Amazon ECS
preStop, porque el período de gracia comienza a contar antes de que el gancho se ejecute en lugar de cuando la puerta de enlace recibe SIGTERM.
Su plataforma también puede limitar cuánto tiempo puede ejecutarse el drenaje:
- Amazon ECS en Fargate:
stopTimeoutpermite como máximo 120 segundos - Cloud Run: detiene una instancia 10 segundos después de
SIGTERM, así que las transmisiones abiertas obtienen como máximo 10 segundos allí, sea cual sea la ventana de drenaje
drain window over after, cuenta las solicitudes que cortó, y nombra ambas configuraciones para aumentar.
Las migraciones son solo anexo, así que revertir a un binario anterior que conoce menos migraciones es seguro; ignora las filas adicionales. La reversión también re-valida el YAML contra el esquema del binario más antiguo, así que una configuración que adoptó una clave introducida por la versión más nueva falla al arrancar en la más antigua. Elimine la nueva clave antes de revertir.
Porque fija la versión de la puerta de enlace en su propia imagen, las correcciones en nuevas versiones de Claude Code, incluidas las correcciones de seguridad, llegan a su implementación solo cuando actualiza el pin y redeploy. Incluya la puerta de enlace en el mismo ciclo de parches que usa para otros servicios que contienen credenciales de producción.
Seguridad
Esta sección responde las preguntas que una revisión de seguridad hace: qué datos fluyen a través de la puerta de enlace y hacia dónde van, qué ataques defiende el diseño, y qué respuestas pertenecen en un cuestionario de cumplimiento.Flujo de datos
Resumen del modelo de amenaza
La puerta de enlace se sienta dentro de su perímetro de red, pero las máquinas portátiles de desarrolladores individuales no se tratan como confiables. El diseño cuenta para esto de tres maneras:- Los desarrolladores sostienen JWTs de corta duración en lugar de claves ascendentes sin procesar. La pierna CLI-a-puerta de enlace usa la concesión de dispositivo RFC 8628, y el intercambio de código de autorización de la puerta de enlace con el IdP ejecuta PKCE en la configuración predeterminada, así que un código de autorización de IdP interceptado es inútil.
- La página de verificación de dispositivo impone POST del mismo origen y un límite de velocidad por IP por RFC 8628 §5.1. Consulte Resistencia de fuerza bruta de código de usuario.
-
Las solicitudes de la puerta de enlace a su IdP, sus recopiladores OTLP, y ascendentes
provider: anthropicpasan por una protección de falsificación de solicitud del lado del servidor (SSRF) que resuelve DNS, bloquea direcciones de enlace local y metadatos en la nube más loopback de forma predeterminada, y fija la conexión a la IP resuelta, así que URLs influenciadas por el operador no pueden ser redirigidas a puntos finales de metadatos en la nube. Los rangos privados RFC 1918 se permiten deliberadamente, porque los IdPs y recopiladores OTLP comúnmente viven en IPs privadas. Para los otros proveedores, la puerta de enlace rechaza unbase_urlque nombre una de esas direcciones o un nombre de host de metadatos cuando carga la configuración, y el SDK del proveedor luego se conecta sin la verificación de DNS. Si activa egreso solo proxy, esa verificación de dirección se mueve a su proxy directo: la puerta de enlace le entrega nombres de host y la lista de permitidos del proxy debe rechazar esos destinos. EstablezcaCLAUDE_GATEWAY_ALLOW_LOOPBACK=1en el entorno de la puerta de enlace solo cuando algo que la puerta de enlace debe alcanzar legítimamente vive en loopback, como un IdP de desarrollo local o un recopilador OTLP sidecar enlocalhost. La variable relaja el bloque de loopback para cada URL configurada por el operador y también omite la advertencia de tiempo de arranque que verifica si el pod puede alcanzar el punto final de metadatos en la nube, así que prefiera dar al recopilador su propia dirección interna.
- Un host de puerta de enlace comprometido: el host tanto contiene la credencial ascendente como distribuye configuraciones administradas a cada desarrollador conectado, así que el control sobre la configuración de la puerta de enlace es comparable al control sobre su MDM. El diálogo de aprobación del CLI para configuraciones capaces de shell limita cambios silenciosos pero no reemplaza la seguridad del host.
- Un proveedor OIDC malicioso: el proveedor firma los id_tokens que la puerta de enlace confía, así que puede afirmar cualquier identidad. Verificar y asegurar su IdP es su responsabilidad.
Resistencia de fuerza bruta de código de usuario
Eluser_code que un desarrollador escribe en la página de verificación /device son 8 caracteres extraídos de un alfabeto de 20 caracteres, que produce 20⁸ o aproximadamente 2.56×10¹⁰ combinaciones, y expira después de 10 minutos.
La puerta de enlace aplica límites de velocidad por IP en los puntos finales de concesión de dispositivo, configurables a través de rate_limits. Aumente los límites si muchos desarrolladores inician sesión desde una única dirección NAT corporativa compartida. Los despliegues grandes muestran cómo dimensionarlos. Los límites se aplican solo al flujo de inicio de sesión, no a la inferencia.
Postura de cumplimiento
- Residencia de datos: el plano de datos propio de la puerta de enlace no envía nada a Anthropic a menos que la API de Anthropic sea un ascendente configurado; cuando lo es, su acuerdo de manejo de datos existente se aplica a la ruta de inferencia. Telemetría, auditoría, identidad y configuraciones van solo a los destinos que configura.
- Tráfico de proceso de host: el proceso de host es el CLI de Claude Code.
claude gatewayse ejecuta bajo las mismas reglas de terceros que las implementaciones de Amazon Bedrock y Google Cloud’s Agent Platform y no envía nada a Anthropic. Antes de v2.1.227, el proceso de host enviaba telemetría de inicio como versión de producto y plataforma, que establecerCLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1en el entorno del contenedor desactivaba. Esos lanzamientos también enviaban una solicitudHEADal arranque, sin cuerpo ni credenciales, a/api/helloenhttps://api.anthropic.com, o enANTHROPIC_BASE_URLcuando el entorno lo establecía, a menos que el entorno también estableciera una variable proxy comoHTTPS_PROXYo un certificado de cliente mTLS. Ignoraban la respuesta, así que bloquear esa solicitud en el firewall de salida no afectaba la puerta de enlace. - Análisis del cliente: el CLI deshabilita su propio análisis de uso y reporte de errores mientras está conectado a una puerta de enlace. Antes del primer inicio de sesión, el CLI aún envía eventos de inicio a Anthropic, incluso en máquinas cuyas configuraciones administradas fuerzan el inicio de sesión de puerta de enlace. Para mantener esos también apagados, entregue
DISABLE_TELEMETRYen las mismas configuraciones administradas del lado del cliente que fuerzan el inicio de sesión de puerta de enlace. - Reporte de errores: el CLI desactiva el reporte de errores siempre que sus solicitudes de modelo vayan a cualquier punto final que no sea la API de primera parte de Anthropic, como Amazon Bedrock o un
ANTHROPIC_BASE_URLpersonalizado. - Máquinas cliente: las CLI de los desarrolladores todavía envían verificaciones de nombres de host de WebFetch y verificaciones de versión a Anthropic, a menos que se establezcan
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1yskipWebFetchPreflight: true. Las solicitudes de marketplaces de plugins tienen sus propios mecanismos para desactivarlas. Consulta uso de datos. - Calificaciones de encuesta: mientras está conectado a una puerta de enlace, el CLI deshabilita la carga de calificación vinculada a Anthropic junto con los flujos de análisis, así que no envía calificaciones a Anthropic.
- Compartir transcripción: elegir Sí en el indicador de compartir transcripción de una encuesta escribe un archivo local bajo
~/.claude/feedback-bundles/en lugar de cargar a Anthropic. - Actualizaciones del cliente: las verificaciones de actualización son separadas del tráfico de puerta de enlace. Fije versiones a través de su propia distribución y establezca
DISABLE_UPDATESsi las máquinas portátiles no deben obtener lanzamientos.DISABLE_AUTOUPDATERdetiene solo actualizaciones de fondo mientrasclaude updateaún funciona. - TLS: sirva
public_urlsobre HTTPS en producción, ya sea desde el oyente propio de la puerta de enlace a través delisten.tlso desde un ingress que termina TLS frente a réplicas HTTP simples, conlisten.public_urlestablecido en ambos casos. La puerta de enlace no rechaza HTTP simple. El IdP debe servir HTTPS en producción, y Postgres admite?sslmode=require. EstablezcaStrict-Transport-Securityen su ingress. - Divulgación de vulnerabilidad: siga Reportar problemas de seguridad
Solicitudes de marketplaces de plugins
Claude Code obtiene los marketplaces de plugins directamente desde la máquina de cada desarrollador, no a través del gateway. Requisitos de acceso a la red enumera los hosts. La primera vez que un desarrollador inicia una sesión interactiva en la terminal, Claude Code registra el marketplace oficial,claude-plugins-official. Descarga el catálogo desde downloads.claude.ai y, si eso falla, lo clona desde github.com. Qué marketplaces y plugins se actualizan automáticamente cubre las actualizaciones posteriores.
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 no detiene el primer registro. Cualquiera de estos ajustes de la configuración administrada sí lo detiene:
- Una lista de marketplaces: una lista de permitidos
strictKnownMarketplacesque deje fuera el marketplace, o una entrada deblockedMarketplacesque lo indique - Una variable de entorno:
CLAUDE_CODE_DISABLE_OFFICIAL_MARKETPLACE_AUTOINSTALLestablecida en"1"en el bloqueenvadministrado
cli o code de la política del gateway.
Solución de problemas
Para preguntas y comentarios, usa el soporte de Claude Code o abre un issue en el repositorio de GitHub de Claude Code. También puedes contactar al equipo de tu cuenta de Anthropic. Al reportar un problema, incluye:- Problema del gateway: el stderr del gateway para el intervalo correspondiente, tu
gateway.yamlcon los secretos ocultos, la versión del gateway, que se muestra en la página de inicio en/y en el encabezado de respuestax-cc-gateway-versionen/managed/settings, y qué cambió recientemente - Problema de inicio de sesión: el desarrollador ejecuta
claude --debug-file ./claude-debug.txt, reproduce el problema y envía ese archivo junto con el registro de auditoría del gateway para el mismo intervalo - Problema de inferencia: el modelo solicitado, los upstreams configurados y el registro de auditoría del gateway para la solicitud, que registra qué upstream la atendió y el estado de la respuesta
El mensaje
Cloud gateway sign-in was not completed indica el nombre de host del gateway. Cuando Claude Code tiene tanto la huella digital fijada como la presentada, el mensaje también muestra los primeros 16 caracteres de cada una.
Si Claude Code informa couldn't load your organization's managed settings después de un inicio de sesión en el gateway, Claude Code indica el motivo, se reinicia en el mismo lugar y reanuda la conversación. Si Claude Code no puede reiniciarse, por ejemplo en una sesión en segundo plano, Claude Code termina la sesión y conserva el inicio de sesión.
Encabezados de solicitud demasiado grandes después de iniciar sesión
Las solicitudes de un desarrollador pueden fallar con un error431 después de iniciar sesión cuando el desarrollador pertenece a muchos grupos del IdP.
El gateway responde 431 cuando los encabezados de una solicitud suman más de 256 KiB, o más de limits.max_request_header_bytes si lo estableces. No escribe ninguna línea de registro ni evento de auditoría para estas solicitudes. Las versiones del gateway anteriores a v2.1.284 responden 431 por encima de 16 KiB.
Empieza por la primera de estas opciones que aplique a tu gateway:
- Gateway anterior a v2.1.284: actualiza el gateway
limits.max_request_header_bytesestablecido: aumenta el valor o elimina la clave- No aplica ninguno de los dos, o el
431continúa después: haz que tu IdP emita menos grupos. Configuración del proveedor de identidad explica cómo Okta, Microsoft Entra ID y Google Workspace proporcionan los grupos
oidc.allowed_groups: decide quién puede iniciar sesiónadmin.admin_groups: decide quién puede llamar a la API de administración con su sesión del gatewaymatch.groupsenmanaged.policies: decide qué política se aplica a un desarrolladorgroupsen un upstream: decide qué upstreams atienden a un desarrollador- Límites de gasto de
rbac_group: deciden qué límites de grupo se aplican a un desarrollador
El pensamiento largo termina en tiempos de espera agotados del proxy
Si tu upstream esprovider: anthropic, usa Pensamiento largo en un upstream de la API de Anthropic en su lugar: allí también aumentas CLAUDE_STREAM_IDLE_TIMEOUT_MS, pero los tiempos y los errores son diferentes.
Si los turnos fallan después de un pensamiento largo y tu proxy registra una solicitud abierta durante unos 12.5 minutos y luego una serie de errores 504, aumenta CLAUDE_STREAM_IDLE_TIMEOUT_MS en una política del gateway. Por ejemplo, con un tiempo de espera de inactividad de 240 segundos en el proxy, la serie es de 10 solicitudes, cada una cortada a los 240 segundos.
- La primera solicitud: un stream que entrega su primer evento de respuesta,
message_start, y luego solo pings mientras Claude piensa. Con la configuración predeterminada, Claude Code termina ese stream después de unos 12.5 minutos. - Las otras 10: la misma solicitud, enviada sin streaming y luego reintentada, 10 envíos en total de forma predeterminada. No reciben pings, así que una respuesta lenta alcanza el tiempo de espera del proxy.
Confirmar la causa
Pide a un desarrollador que reproduzca el fallo conclaude --debug-file ./claude-debug.txt y luego busca esta línea en ese archivo:
CLAUDE_CODE_DISABLE_NONSTREAMING_FALLBACK en 1, no ves solicitudes sin streaming, y el turno termina con API Error: Stream idle timeout - no chunks received. Se aplica la misma solución.
Elegir un valor
Elige un valor deCLAUDE_STREAM_IDLE_TIMEOUT_MS cuya segunda columna cubra tu pausa de pensamiento más larga, o empieza con 1800000 si no la conoces. Un stream puede mantenerse solo con pings unos 7.5 minutos más que el valor:
Si un upstream se cuelga mientras el gateway sigue enviando pings, tus desarrolladores también esperan ese tiempo antes de que Claude Code abandone el stream. Una conexión que queda completamente en silencio sigue terminando después de 5 a 6 minutos, porque el tiempo de espera de inactividad del cuerpo no sigue esta variable.
Entregar el valor en una política
Agrega la entradaenv a cada política de gateway.yaml que ya entrega configuración de Claude Code a los desarrolladores que quieres cubrir. Colócala bajo la clave code, cli o settings que esa política ya tiene. Para probar el valor primero, empieza con una política que coincida con un grupo. Consulta managed para saber cómo las políticas coinciden y heredan. Este ejemplo agrega la entrada a una política match: {} con la clave cli:
cli, cubres las sesiones de la terminal, de la extensión del IDE y del Agent SDK. Para la pestaña Code de Claude Desktop, consulta Elegir cli o code.
Reinicia el gateway para que lea el archivo editado. Luego pide a los desarrolladores que reinicien Claude Code para obtener CLAUDE_STREAM_IDLE_TIMEOUT_MS.
Pensamiento largo en un upstream de la API de Anthropic
Siprovider: anthropic es el único upstream del modelo y tu proxy registra una solicitud abierta durante unos 20 minutos y luego errores 502 o 504, aumenta CLAUDE_STREAM_IDLE_TIMEOUT_MS en una política del gateway.
- La solicitud larga: un stream que entrega
message_starty luego solo pings mientras Claude piensa. Claude Code lo termina después de unos 20 minutos con la configuración predeterminada, y más tarde una vez que aumentas la variable. - Los errores: solicitudes que Claude Code luego envía sin streaming. Cada una falla con un
502del gateway, o con el504de tu proxy si el tiempo de espera del proxy es más corto que la espera del gateway. Esa espera estimeouts.upstream_ttfb_ms, que no necesitas aumentar para esta solución.
900000 y 45 con 1800000. Luego sigue Entregar el valor en una política.
Relacionado
- Descripción general de la puerta de enlace de aplicaciones Claude: inicio rápido y conexión de desarrolladores
- Referencia de configuración: cada opción de
gateway.yaml