Pianifica prima la rete del tuo gateway. All’accesso, Claude Code rifiuta un gateway delle app Claude il cui nome host si risolve in un indirizzo IP pubblico, anche se non è raggiungibile da internet.Un gateway delle app Claude può inviare impostazioni alle macchine degli utenti, inclusi hook che eseguono comandi della shell. Il controllo aiuta a evitare che gli utenti accedano accidentalmente a un gateway dannoso su internet pubblico. Tieni anche il tuo gateway fuori da internet.Scegli l’indirizzo del gateway prima di scegliere dove eseguirlo. Di solito si tratta di un indirizzo privato che gli utenti raggiungono sulla tua rete interna o tramite una VPN. Se la tua rete interna usa intervalli IPv4 pubblici, puoi indicare un intervallo che contenga sia il gateway sia le macchine dei tuoi utenti. Claude Code interpreta questa corrispondenza come un segnale che il gateway si trova sulla tua rete interna. Consulta Scegliere un indirizzo per il gateway. Se nessuna delle due opzioni è adatta alla tua rete, contatta il tuo team di riferimento Anthropic.
gateway.yaml che il gateway legge all’avvio, consultare il Riferimento di configurazione.
Una distribuzione in produzione segue quattro passaggi in ordine, e le sezioni sottostanti li corrispondono. I primi due sono dove fate scelte; i secondi due sono materiale di riferimento da consultare una volta che è in esecuzione.
- Configurare il vostro provider di identità: registrare il client OAuth e controllare le note specifiche per IdP per Okta, Entra e Google
- Distribuire il gateway: costruire un’immagine container con versione fissa ed eseguirla su Kubernetes, Cloud Run, o la vostra piattaforma. Questa sezione copre anche decisioni relative a costi, bypass, gateway multipli e serverless
- Configurare le operazioni: log, sonde di integrità, comportamento in caso di interruzione, rotazione dei segreti e aggiornamenti. Riferimento per quando state collegando il monitoraggio e i runbook
- Esaminare la postura di sicurezza: dove fluiscono i dati, il modello di minaccia e le risposte sulla conformità. Riferimento per una revisione della sicurezza
Configurazione del provider di identità
Registra un’applicazione web OAuth/OpenID Connect (OIDC) confidenziale con un singolo URI di reindirizzamento,https://<gateway>/oauth/callback, e assegnala agli utenti o ai gruppi che dovrebbero avere accesso al gateway. Il gateway si autentica presso l’IdP con il client secret della registrazione, oppure con un certificato che carichi nella registrazione se il tuo IdP usa invece le credenziali con certificato.
Qualsiasi IdP conforme a OIDC funziona: Okta, Microsoft Entra ID, Google Workspace, Keycloak, Dex, PingFederate e altri. L’IdP deve soddisfare tre requisiti:
- Serve
/.well-known/openid-configuration, su HTTPS in produzione; il gateway accetta unhttp://issuer, e un issuer loopback richiede inoltreCLAUDE_GATEWAY_ALLOW_LOOPBACK=1 - Supporta il flusso authorization-code. PKCE (Proof Key for Code Exchange) è attivo per impostazione predefinita; disabilitalo con
oidc.use_pkce: falseper IdP che non lo supportano - Restituisce
emaile facoltativamentegroupsnell’id_token, o li serve dall’endpoint userinfo conoidc.userinfo_fallback: true
oidc.ca_cert_pem.
Alcuni provider gestiscono i claim di email e gruppo diversamente:
- Okta: il server di autorizzazione dell’organizzazione in
https://example.okta.comrestituisce un id_token sottile che ometteemailegroups, quindi impostaoidc.userinfo_fallback: trueogni volta che lo usi comeissuer. Un server di autorizzazione personalizzato comehttps://example.okta.com/oauth2/defaultche includeemaile facoltativamentegroupsnell’id_token li emette direttamente e non ha bisogno di fallback. Okta emettegroupssolo quando lo scopegroupsè richiesto inoidc.scopese il filtro dei claim dei gruppi dell’app lo consente;userinfo_fallbacknon può riempire un claim per il quale l’IdP non è stato interrogato. - Microsoft Entra ID:
issuer=https://login.microsoftonline.com/<tenant-id>/v2.0. Entra emette Object ID dei gruppi piuttosto che nomi, quindi usa i GUID inmanaged.policies.match.groups, o usa App Roles per nomi leggibili. Se il tuo tenant emette ruoli sottorolesinvece digroups, impostaoidc.groups_claim: roles. - Google Workspace:
issuer=https://accounts.google.com. L’id_token di Google non contiene gruppi. Per usareallowed_groupsbasato su gruppi omanaged.policiescon Google come IdP, configuraoidc.google_groups, che cerca i gruppi di ogni utente tramite l’API Admin SDK Directory usando un account di servizio con delega a livello di dominio. Senza di esso, usaoidc.allowed_email_domainsper il gating dell’appartenenza emanaged.policies.match.email_domainper l’assegnazione della policy. Google ignora anche lo scope standardoffline_access. Per i token di aggiornamento, impostaoidc.scopes: [openid, profile, email]eoidc.extra_auth_params: { access_type: offline, prompt: consent }.
Distribuzione
Il gateway è un singolo binario Linux senza stato che si coordina attraverso Postgres, quindi distribuiscilo come distribuisci qualsiasi altro servizio senza stato nel tuo ambiente. Mantienilo all’interno della tua rete, dove i tuoi sviluppatori possono raggiungerlo su HTTPS e da dove esso può raggiungere il tuo IdP, e trattalo come qualsiasi servizio che contiene una credenziale di produzione. Alcune decisioni modellano la distribuzione oltre a dove viene eseguito:- Costo: nessuna licenza separata o tassa per posto. Il gateway fa parte del binario
claude, quindi paghi per l’inferenza attraverso il tuo impegno esistente, più il calcolo su cui viene eseguito. - Bypass: il gateway non applica che l’unica rotta a un modello passi attraverso di esso. Uno sviluppatore con la propria credenziale può comunque chiamare il provider direttamente, quindi chiudere quel percorso è una decisione di policy di rete, ad esempio bloccando l’uscita verso
api.anthropic.comtranne dal gateway. Bloccare anche quell’uscita interrompe il controllo di sicurezza del dominio WebFetch, che chiamaapi.anthropic.comda ogni macchina dello sviluppatore. ImpostaskipWebFetchPreflight: truenella policy gestita per disabilitarlo. - Gateway multipli: ogni gateway è una distribuzione separata con la sua configurazione, e il CLI memorizza la fiducia e le credenziali per nome host del gateway, quindi i team possono utilizzare gateway diversi senza conflitto. Per servire più emittenti OIDC, esegui istanze separate.
- Serverless: Cloud Run funziona se imposti
min-instances: 1per evitare il cold start della scoperta OIDC. Lambda e Cloud Functions non funzionano, perché il gateway è un server HTTP a lunga durata.
listen.trusted_proxies agli intervalli di origine del proxy in modo che il gateway legga gli IP client da X-Forwarded-For. Il gateway onora l’intestazione solo quando il peer TCP è affidabile. Gli esempi elaborati di Google Cloud e AWS hanno valori concreti per topologia. Senza proxy affidabili, ogni richiesta sembra provenire dall’IP del proxy, il che comprime i limiti di velocità per IP in un bucket condiviso e registra l’IP del proxy negli eventi di audit.
Non reindirizzare le richieste agli endpoint di autorizzazione del dispositivo e token del gateway, ad esempio con una riscrittura HTTP-to-HTTPS o di canonicalizzazione dell’host all’ingress. Claude Code non segue i reindirizzamenti su quelle richieste, quindi una regola di ingress che le reindirizza interrompe l’accesso e l’aggiornamento del token.
Dai al proxy un timeout di inattività più lungo dell’intervallo di keepalive del gateway, che dipende dall’upstream:
- Su ogni upstream tranne
provider: anthropic, il gateway scrive unpingSSE una volta che un flusso è stato silenzioso per circa 15 secondi. - Su
provider: anthropic, il gateway passa la risposta invariata, inclusi i ping dell’API Anthropic.
Scegli un indirizzo per il gateway
Claude Code accetta l’indirizzo di un gateway in uno di due modi:- Indirizzo privato: metti il gateway dietro un load balancer interno o una VPN, con un nome host che si risolve solo in indirizzi privati, come RFC 1918 o CGNAT
100.64.0.0/10. Le macchine degli utenti possono avere qualsiasi indirizzo. Il prerequisito della rete privata elenca gli intervalli accettati. - Blocco dichiarato: se la tua rete interna utilizza spazio IPv4 pubblico di proprietà della tua organizzazione, elenca il blocco nell’impostazione gestita
gatewayInternalNetworks. Il gateway e la macchina dell’utente devono trovarsi entrambi in quel blocco. Consulta Consentire un gateway su spazio di indirizzi pubblico di tua proprietà.
Immagine del container
Costruisci la tua immagine attorno al binarioclaude nativo dalla versione standard di Claude Code:
- Scarica la build Linux per l’architettura della tua immagine da una versione fissa; consulta Installa una versione specifica per l’URL di download.
- Verificalo rispetto al
manifest.jsonfirmato con GPG della versione come descritto in Integrità binaria e firma del codice. - Copialo nel contesto di build.
- Un’immagine basata su glibc: la build glibc ha solo dipendenze dinamiche dalle librerie glibc. Le immagini basate su Musl hanno bisogno della build
linux-x64-muslolinux-arm64-musl, la cui unica dipendenza dinamica è musl. - Una directory di stato scrivibile: il gateway funziona come qualsiasi utente, ma le immagini minime non hanno home scrivibile. Imposta
CLAUDE_CONFIG_DIRa un percorso scrivibile come/tmp/.claude. - Il comando del container:
claude gateway --config /etc/claude/gateway.yaml, con il file di configurazione montato in sola lettura e i segreti forniti come variabili di ambiente; il gateway ascolta sulisten.port, predefinito8080.
Kubernetes
Esegui il gateway come Deployment, come qualsiasi servizio senza stato:- Monta la configurazione da una ConfigMap e i segreti da un Secret; fai riferimento ai segreti nel YAML tramite
${file:/path/to/secret}o come variabili di ambiente - Termina TLS all’Ingress e imposta
listen.public_urlal nome host dell’Ingress - Punta la sonda di readiness a
GET /readyze la sonda di liveness aGET /healthz
upstreams ha dettagli di configurazione per piattaforma. Per un accoppiamento cross-cloud, come un upstream Bedrock su GKE, imposta credenziali esplicite nel blocco auth dell’upstream.
Cloud Run
Configura il servizio come segue:- Lascia
listen.portal suo predefinito di8080, che corrisponde alPORTpredefinito di Cloud Run, o impostaport: ${PORT} - Imposta
public_urlall’origine esternamente raggiungibile. Per la produzione questo è normalmente il nome host di un load balancer interno, perché/loginrifiuta gli indirizzi pubblici e l’URL*.run.appsi risolve in uno, quindi l’URL di Cloud Run da solo funziona solo per un test di fumocurlo browser. L’eccezione è una rete dove*.run.appsi risolve privatamente tramite Private Service Connect e una zona privata di Cloud DNS; in quella topologia l’URL di Cloud Run è unpublic_urlvalido. L’esempio elaborato di Google Cloud copre entrambi. - Monta la configurazione come volume segreto
- Imposta
min-instances: 1per evitare il cold start della scoperta OIDC alla prima richiesta
Invia l’URL del gateway alle macchine degli sviluppatori
Una volta che il gateway è in servizio, inviaforceLoginMethod, forceLoginGatewayUrl e parentSettingsBehavior: "merge" a ogni macchina dello sviluppatore tramite impostazioni gestite, tramite MDM o scrivendo direttamente il managed-settings.json per OS.
Una volta che distribuisci le chiavi, Claude Code smette di utilizzare una chiave API rimasta o un accesso a claude.ai sulla macchina, quindi pianifica il push insieme alle tue istruzioni di accesso. La policy dell’amministratore richiede un accesso al gateway Cloud descrive i messaggi che gli sviluppatori vedono.
Consulta dove ogni meccanismo memorizza la policy per i percorsi dei file, e Impostazioni gestite lato client per l’equivalente bootstrapUrl di Claude Desktop.
Rollout su larga scala
L’accesso è limitato per indirizzo IP client, e i valori predefiniti si adattano a un piccolo team. Ogni indirizzo ottiene 30 avvii di accesso e 10 invii di codice ogni 10 minuti. Un rollout a migliaia di sviluppatori può raggiungere questi limiti la prima mattina, per uno di due motivi:- Il gateway non può vedere oltre il tuo load balancer. Senza
listen.trusted_proxies, ogni sviluppatore sembra provenire dall’indirizzo del load balancer e condivide un unico limite. Il gateway registra un avviso la prima volta che ignora un’intestazioneX-Forwarded-For. Se il load balancer va incluso inlisten.trusted_proxies, elencalo prima di modificare qualsiasi altra cosa. Se gli sviluppatori condividono ancora un unico indirizzo, aumentarate_limits. - Molti sviluppatori condividono pochi indirizzi di uscita NAT o VPN. Condividono i limiti di quegli indirizzi anche quando
trusted_proxiesè corretto. Aumentarate_limitsper adattarsi.
max, dividi gli sviluppatori per gli indirizzi di uscita che condividono. Stima quanti di loro accedono entro un periodo window_seconds, che è 10 minuti per impostazione predefinita. Quindi raddoppialo per coprire i tentativi e gli sviluppatori che accedono sia a Claude Code che a Claude Desktop.
Ad esempio, 10.000 sviluppatori dietro 4 indirizzi di uscita accedono uniformemente in un’ora. Cioè 2.500 sviluppatori per indirizzo e circa 420 di loro in ogni 10 minuti, che raddoppi e arrotondi a 1.000. L’esempio seguente imposta entrambi i limiti a 1.000:
device_verify è quello che impedisce a qualcuno di indovinare il codice di accesso di un altro sviluppatore, quindi aumentalo solo quanto la tua stima ha bisogno. Anche a questi limiti, un codice è 8 caratteri da un alfabeto di 20 caratteri e scade dopo 10 minuti, quindi indovinare rimane impraticabile; consulta Resistenza al brute-force del codice utente.
Quando il tuo IdP emette token di aggiornamento, Claude Code rinnova le sessioni silenziosamente, quindi puoi rimettere il limite dopo il rollout. Senza token di aggiornamento, gli sviluppatori accedono di nuovo ogni session.ttl_hours. Dimensiona entrambi i limiti anche per quel tasso costante e lasciali aumentati.
Quando un limite viene raggiunto, Claude Code v2.1.274 o successivo mostra The gateway is limiting sign-in attempts right now. Un gateway su v2.1.274 o successivo mostra Too many attempts came from your network address sulla pagina di verifica, con le impostazioni da controllare. Scrive anche una riga di log sign-in refused che nomina l’impostazione da modificare.
Operazioni
Una volta che il gateway sta servendo il traffico, l’operazione quotidiana consiste nel leggere i suoi log, sondare la sua salute e ruotare i suoi segreti secondo il tuo programma. Le sottosezioni coprono ciascuno, più quello che Postgres contiene e come gli aggiornamenti e i rollback si comportano.Log
Il gateway scrive due flussi su stderr, entrambi JSON-friendly:-
Eventi di audit: JSON a riga singola per evento rilevante per la sicurezza. Invia stderr al tuo aggregatore di log.
Gli eventi emessi includono
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.upsert, eadmin.limit.delete. I campi variano per evento:- Gli eventi di mint e refresh riusciti portano
sub,email,client_ip, e il risultato auth.deniedeaccess.deniedportano il motivo e l’IP client, più il percorso della richiesta perauth.denied, poiché nessuna identità utente esiste in quelle negazioni. Due motivi diaccess.deniedcambiano quello che l’evento porta:xff_unparseable: l’evento porta anche la voceX-Forwarded-Forche non poteva essere lettaclient_ip_unknown: l’evento non porta alcun IP client, perché la connessione non aveva un indirizzo peer mentre era impostato un elencoaccess_control
access.public_clientporta l’IP client della prima richiesta per processo che arriva da un indirizzo pubblico mentreaccess_control.allow_cidrsè vuoto. Il gateway serve la richiesta come al solito; l’evento segnala che il gateway potrebbe essere raggiungibile da internet pubblico. Vedi il riferimentoaccess_controlper quello che conta come pubblico e per l’elenco di autorizzazione consigliato.inferenceregistra quale upstream ha servito la richiesta e lo stato della rispostadesktop_bootstrap.deniedregistra un fetch di bootstrap di Claude Desktop rifiutato con il motivo (not_configured,policy_not_opted_in, ono_policy_matched) e l’identità dell’utenteguardrail.traceregistra quale filtro è scattato, senza il testo corrispondenteadmin.deniedregistra un tentativo di autenticazione dell’API di amministrazione rifiutato con l’IP client, il metodo, il percorso e un motivo, senza il materiale della chiave presentato:invalid_keyquando è stato presentato unx-api-keyma non ha corrisposto a nessuna chiave configurata,bearer_rejectedquando è stato presentato solo un headerAuthorizatione non si è verificato come una sessione gateway inadmin.admin_groups, ono_credentialsquando nessun header è stato presentato
- Gli eventi di mint e refresh riusciti portano
-
Log operazionali: righe leggibili con prefisso
[gateway]per avvio, avvertimenti e errori upstream. La variabile di ambienteCLAUDE_GATEWAY_LOG_LEVELcontrolla la verbosità e accettadebug,info,warn, oerror, coninfocome predefinito. Adebug, ogni accesso e aggiornamento registra anche i nomi, non i valori, dei claim nell’id_token, più i nomi dei claim userinfo quandouserinfo_fallbackha fornito qualcosa, così puoi diagnosticare le impostazioniemail_claimegroups_claimsenza registrare PII. Non influisce sugli eventi di audit, che sono sempre emessi.
Scrivi i log operazionali in JSON
Se il tuo raccoglitore di log legge il livello di ogni riga da un campo JSON, impostaCLAUDE_GATEWAY_LOG_FORMAT=json nell’ambiente del gateway. Richiede Claude Code v2.1.319 o successivo sul server del gateway.
Ogni riga di log operazionale diventa quindi un oggetto con severity, time e message:
severity è il livello di log in maiuscolo, con warn scritto come WARNING. Un avvio non riuscito è una riga ERROR.
Gli eventi di audit, che vanno anch’essi su stderr, non cambiano. Portano ts e evt, e nessun severity.
Salute
Il gateway serveGET /healthz come sonda di liveness e GET /readyz come sonda di readiness. /readyz verifica che lo store sia raggiungibile. Se imposti store.readiness_grace_seconds, /readyz continua a segnalare ready per fino a quel numero di secondi dopo che lo store smette di rispondere.
Entrambi gli endpoint sono esenti da access_control.allow_cidrs, quindi le sonde continuano a funzionare su un listener bloccato.
Il documento di scoperta OAuth in /.well-known/oauth-authorization-server restituisce anche 200 solo dopo il caricamento della configurazione, la scoperta OIDC, la costruzione del client upstream e la migrazione di Postgres, quindi funge anche da controllo di avvio end-to-end.
Richieste upstream concorrenti
Per impostazione predefinita, ogni replica del gateway invia al massimo 256 richieste upstream contemporaneamente. Una risposta in streaming conta rispetto al limite fino al termine dello stream. Una richiesta che arriva mentre una replica è al limite attende all’interno del gateway per uno slot libero. Lo sviluppatore vede una risposta che è lenta a iniziare o sembra bloccarsi. Su un upstreamprovider: anthropic, una richiesta che attende più a lungo di timeouts.upstream_ttfb_ms rinuncia a quell’upstream e fallisce con un 502 quando nessun upstream successivo lo serve.
La riga di log di avvio che contiene upstream requests: mostra il limite in vigore. Mentre una replica ha più richieste aperte rispetto al limite, registra anche un avvertimento che contiene client requests are open, al massimo una volta al minuto.
Per servire più richieste contemporaneamente, hai due opzioni:
- Aggiungi repliche.
- Aumenta il limite su ogni replica. Imposta la variabile di ambiente
BUN_CONFIG_MAX_HTTP_REQUESTSsul contenitore del gateway su un numero intero da 1 a 65535, quindi riavvia il contenitore.
client requests are open.
In un test di carico con load_test_mode, le richieste non attendono a questo limite, ma una replica registra comunque l’avvertimento client requests are open.
Mantieni API_TIMEOUT_MS al di sopra del tempo al primo byte del gateway
Se abbassi API_TIMEOUT_MS per riprovare prima una richiesta senza risposta, mantienilo al di sopra del tempo che il gateway impiega per inviare i primi byte di una risposta in streaming. Una richiesta che attende più a lungo va in timeout, e lo stesso accade a ogni nuovo tentativo che attende altrettanto, finché il turno non termina con Request timed out, a meno che non lo termini la scadenza del primo byte.
provider: anthropic: impostaAPI_TIMEOUT_MSal di sopra del tempo più lungo che il tuo upstream impiega per inviare il suo primo evento.- Ogni altro upstream: impostalo a più di 20 secondi oltre il tempo più lungo che il tuo upstream impiega per restituire gli header della risposta. Il gateway invia il suo primo
pingdi keepalive circa 15 secondi dopo quegli header, a meno che il primo evento dell’upstream non arrivi prima. Un gateway precedente alla v2.1.229 non invia ping, quindi in quel caso usa la regola diprovider: anthropic.
Riprova prima una richiesta senza risposta con la scadenza del primo byte
Per fare in modo che Claude Code riprovi prima una richiesta in streaming senza risposta, assegnagli una scadenza del primo byte impostandoCLAUDE_STREAM_FIRST_BYTE_TIMEOUT_MS sui computer dei tuoi sviluppatori. La scadenza limita quanto a lungo il primo tentativo attende gli header della risposta. Senza di essa, quel tentativo può attendere da 5 a 6 minuti. Richiede Claude Code v2.1.307 o successivo sul computer dello sviluppatore.
Imposta la variabile su un numero intero positivo di millisecondi, nel blocco env di una policy del gateway o nella shell di uno sviluppatore. Mantieni il valore al di sopra del tempo al primo byte più lungo del tuo gateway, altrimenti Claude Code può interrompere e inviare di nuovo richieste integre i cui header impiegano più tempo. Questo esempio imposta 60 secondi nella shell di uno sviluppatore:
API_TIMEOUT_MS solo per riprovare prima, rimuovi quel valore, altrimenti un solo nuovo invio senza risposta può terminare il turno con No response from API.
Per confermare che la scadenza sia scattata, chiedi a uno sviluppatore di avviare Claude Code con il logging di debug, quindi cerca nel log [first-byte] no response headers.
Comportamento in caso di interruzione
Se Postgres si arresta, il gateway stesso continua a servire gli sviluppatori che hanno effettuato l’accesso e i nuovi accessi falliscono. Se gli sviluppatori effettivamente continuano a lavorare dipende da come il tuo orchestrator gestisce la readiness:- Sessioni esistenti: i bearer token si convalidano localmente con il segreto JWT, gli aggiornamenti della sessione non toccano lo store, e il processo del gateway può comunque servire l’inferenza
- Nuovi accessi: falliscono fino al recupero di Postgres, perché il flusso del dispositivo e i suoi contatori di limite di velocità vivono in Postgres
- Applicazione del limite di spesa: fallisce aperto per impostazione predefinita durante l’interruzione, quindi l’inferenza continua a fluire; capovolgilo per fallire chiuso se preferisci bloccare piuttosto che eseguire senza misurazione
- Readiness: per impostazione predefinita
/readyzsegnala non-ready non appena Postgres è irraggiungibile, quindi ogni replica fallisce il suo controllo di readiness contemporaneamente. Dove il traffico raggiunge solo le repliche che superano il controllo, tutto il traffico, inclusa l’inferenza che il gateway potrebbe comunque servire, fallisce fino al recupero di Postgres. La sonda di liveness su/healthzcontinua a passare durante tutto il tempo.
ttl_hours e i nuovi accessi falliscono. Un aggiornamento della sessione riceve una risposta di riprovare e ha successo una volta che l’IdP è di nuovo disponibile. Imposta un ttl_hours più lungo se il tuo IdP ha frequenti finestre di manutenzione.
Periodo di grazia della readiness
Per mantenere gli sviluppatori che hanno effettuato l’accesso al lavoro attraverso una breve interruzione di Postgres come un failover del database, impostastore.readiness_grace_seconds a più lungo di quanto impiega il failover, ad esempio 300. Con i limiti di spesa attivi e il comportamento predefinito fail-open, le richieste attraverso una replica che rimane ready non sono misurate fino al recupero di Postgres, quindi mantieni il valore il più basso possibile che copra il tuo failover. Se imposti enforcement.fail_closed_on_error: true, il gateway rifiuta l’inferenza degli sviluppatori che hanno effettuato l’accesso con il messaggio 429 spend limit unavailable fino al recupero di Postgres, anche mentre le repliche continuano a superare il loro controllo di readiness.
L’impostazione richiede Claude Code v2.1.282 o successivo sul server del gateway. Un gateway precedente rifiuta di avviarsi quando trova la chiave, quindi aggiorna ogni replica prima di aggiungerla. Aggiornamenti copre il rollback.
Se punti la sonda di readiness a /healthz invece, le repliche continuano a superarla durante un’interruzione, ma /healthz non segnala mai non-ready, quindi una replica il cui collegamento Postgres non si recupera continua a superare anche quella.
Rotazione del segreto JWT
Ruota il segreto di firma in fasi in modo che le sessioni esistenti rimangono valide:- Genera un nuovo segreto. Anteponi l’array
session.jwt_secret. - Esegui il rollout della distribuzione. I nuovi token firmano con il nuovo segreto; i vecchi token si convalidano comunque.
- Dopo
ttl_hourspiù un margine, rimuovi il vecchio segreto ed esegui di nuovo il rollout.
ttl_hours.
Postgres
Il gateway memorizza il suo stato in un database PostgreSQL:- Database: PostgreSQL stesso, self-hosted o gestito, alla versione minima o successiva. I database che implementano solo il protocollo Postgres, come i database SQL distribuiti, non sono supportati.
- Indirizzo:
store.postgres_urlaccetta un solo host. Se il database ha più nodi, usa l’indirizzo che si trova davanti a essi, come l’endpoint del tuo servizio gestito, un load balancer o un IP virtuale. Imposta un periodo di grazia della readiness più lungo di quanto impiega un failover.
_migrations, tutte create dalle sue migrazioni al momento dell’avvio:
Un ciclo di 30 secondi scade le righe
kv oltre il loro TTL, e una pulizia oraria applica le finestre di conservazione sulle tabelle di spesa, quindi nulla cresce senza limiti. Senza limiti di spesa configurati, solo kv viene scritto. Il gateway applica le sue proprie migrazioni dello schema all’avvio e ad ogni aggiornamento, quindi il suo ruolo di database ha bisogno di diritti per creare e alterare le tabelle. Puntalo a un database o schema dedicato al gateway per mantenere quel grant stretto.
Con limiti di spesa in uso, un database perso significa perdita di tracciamento della spesa e limiti, non solo re-accessi degli sviluppatori, quindi esegui backup regolari. Per cancellare immediatamente uno sviluppatore partito piuttosto che aspettare la conservazione, esegui DELETE FROM principal_emails WHERE principal = '<sub>' direttamente; questo rimuove l’unica tabella che contiene la loro email, nome e gruppi. Le righe spend e admin_audit fanno riferimento solo allo pseudonimo OIDC sub.
Dimensiona il pool di connessioni
Ogni replica apre fino astore.max_connections connessioni Postgres, cinque per impostazione predefinita. Mantieni repliche × store.max_connections pari o inferiore alle connessioni che il database ha ancora disponibili per il gateway:
- Repliche: conta il numero massimo in esecuzione contemporaneamente. Parti dal tuo massimo di autoscaling, o dal numero di repliche se non usi l’autoscaling, e aggiungi le repliche extra che un aggiornamento rolling avvia prima di arrestare quelle vecchie. Su Amazon ECS con le impostazioni predefinite, e su Cloud Run, possono essere altrettante.
- Connessioni disponibili: prendi il
max_connectionsdel database, quindi sottrai quelle che il database riserva e quelle occupate da altri client. PostgreSQL riservasuperuser_reserved_connections, tre per impostazione predefinita. Un servizio gestito può riservarne di più, quindi consulta la sua documentazione.
max_connections di 50 e due connessioni occupate da altri client ne ha 50 − 3 − 2 = 45 disponibili, quindi il totale rientra.
Se il tuo totale non rientra, modifica uno di questi elementi:
- Il database: aumenta il suo
max_connections - Le repliche: eseguine meno, o fai in modo che il tuo orchestrator avvii meno repliche extra in un aggiornamento rolling
- Il pool: abbassa
store.max_connections, ma con i limiti di spesa attivi, mantienilo abbastanza grande per il carico di ogni replica. Altrimenti i controlli di spesa possono andare in timeout in attesa di una connessione, e il gateway registraspend check failed: spend precheck timed out.
Aggiornamenti
Le repliche sono senza stato, quindi un riavvio rolling non perde alcuno stato del gateway. Il gateway esegue migrazioni dello schema all’avvio, il che significa che distribuire il nuovo binario auto-migra il database. Le repliche concorrenti si serializzano su un lock consigliato di Postgres, quindi solo una applica ogni migrazione. Quando il tuo orchestrator arresta una replica conSIGTERM, come in un riavvio rolling o uno scale-in, il gateway smette di accettare nuove connessioni e lascia che le richieste e gli stream già in volo finiscano prima di uscire. Attende fino a 25 secondi, chiamato la finestra di drenaggio, quindi chiude tutto ciò che è ancora aperto. Un SIGINT, come Ctrl+C in un terminale, avvia lo stesso drenaggio, e un secondo segnale durante il drenaggio chiude le richieste aperte ed esce subito. Il drenaggio richiede gateway v2.1.274 o successivo.
Le generazioni lunghe possono eseguire lo streaming per minuti. Su Kubernetes e Amazon ECS, aumenta entrambi questi insieme per dare a quegli stream più tempo:
- La finestra di drenaggio: imposta la variabile di ambiente
CLAUDE_GATEWAY_DRAIN_TIMEOUT_MSsul contenitore del gateway su un numero intero positivo di millisecondi, come120000. Il gateway ignora un valore in qualsiasi altra forma, come120s, e mantiene il predefinito di 25 secondi - Il periodo di grazia del tuo orchestrator:
terminationGracePeriodSecondssu Kubernetes, ostopTimeoutsu Amazon ECS
preStop, perché il periodo di grazia inizia a contare prima che l’hook venga eseguito piuttosto che quando il gateway riceve SIGTERM.
La tua piattaforma potrebbe anche limitare quanto a lungo il drenaggio può eseguire:
- Amazon ECS su Fargate:
stopTimeoutconsente al massimo 120 secondi - Cloud Run: arresta un’istanza 10 secondi dopo
SIGTERM, quindi gli stream aperti ottengono al massimo 10 secondi lì, qualunque sia la finestra di drenaggio
drain window over after, conta le richieste che ha tagliato e nomina entrambe le impostazioni da aumentare.
Le migrazioni sono append-only, quindi il rollback a un binario precedente che conosce meno migrazioni è sicuro; ignora le righe extra. Il rollback ri-convalida anche il YAML rispetto allo schema del binario più vecchio, quindi una configurazione che ha adottato una chiave introdotta dalla versione più recente fallisce l’avvio su quella più vecchia. Rimuovi la nuova chiave prima di eseguire il rollback.
Poiché fissi la versione del gateway nella tua immagine, le correzioni nelle nuove versioni di Claude Code, incluse le correzioni di sicurezza, raggiungono la tua distribuzione solo quando aggiorni il pin e ridistribuisci. Includi il gateway nello stesso ciclo di patching che usi per altri servizi che contengono credenziali di produzione.
Sicurezza
Questa sezione risponde alle domande che una revisione di sicurezza pone: quali dati fluiscono attraverso il gateway e dove vanno, quali attacchi il design difende, e quali risposte appartengono a un questionario di conformità.Flusso di dati
Riepilogo del modello di minaccia
Il gateway si trova all’interno del perimetro della tua rete, ma i singoli laptop degli sviluppatori non sono considerati affidabili. Il design tiene conto di questo in tre modi:- Gli sviluppatori detengono JWT di breve durata invece di chiavi upstream grezze. La gamba CLI-to-gateway utilizza la concessione del dispositivo RFC 8628, e lo scambio di autorizzazione del gateway con l’IdP esegue PKCE nella configurazione predefinita, quindi un codice di autorizzazione IdP intercettato è inutile.
- La pagina di verifica del dispositivo applica POST della stessa origine e un limite di velocità per IP per RFC 8628 §5.1. Consulta Resistenza al brute-force del codice utente.
-
Le richieste del gateway al tuo IdP, ai tuoi collettori OTLP e agli upstream
provider: anthropicpassano attraverso una guardia SSRF (Server-Side Request Forgery) che risolve DNS, blocca gli indirizzi link-local e cloud-metadata più loopback per impostazione predefinita, e fissa la connessione all’IP risolto, quindi gli URL influenzati dall’operatore non possono essere reindirizzati agli endpoint dei metadati cloud. Gli intervalli privati RFC 1918 sono deliberatamente consentiti, perché gli IdP e i collettori OTLP comunemente vivono su IP privati. Per gli altri provider, il gateway rifiuta unbase_urlche nomina uno di quegli indirizzi o un nome host di metadati quando carica la configurazione, e l’SDK del provider si connette quindi senza il controllo DNS. Se attivi egress solo proxy, quel controllo di indirizzo si sposta al tuo proxy in avanti: il gateway consegna i nomi host e la lista di consentiti del proxy deve rifiutare quelle destinazioni. ImpostaCLAUDE_GATEWAY_ALLOW_LOOPBACK=1nell’ambiente del gateway solo quando qualcosa che il gateway deve raggiungere legittimamente vive su loopback, come un IdP di sviluppo locale o un collettore OTLP sidecar sulocalhost. La variabile rilassa il blocco loopback per ogni URL configurato dall’operatore e salta anche l’avviso al momento dell’avvio che controlla se il pod può raggiungere l’endpoint dei metadati cloud, quindi preferisci dare al collettore il suo indirizzo interno.
- Un host gateway compromesso: l’host sia contiene la credenziale upstream che distribuisce impostazioni gestite a ogni sviluppatore connesso, quindi il controllo sulla configurazione del gateway è paragonabile al controllo sul tuo MDM. La finestra di dialogo di approvazione del CLI per le impostazioni in grado di shell limita i cambiamenti silenziosi ma non sostituisce la sicurezza dell’host.
- Un provider OIDC malintenzionato: il provider firma gli id_token che il gateway si fida, quindi può asserire qualsiasi identità. Il vetting e la protezione del tuo IdP è tua responsabilità.
Resistenza al brute-force del codice utente
Iluser_code che uno sviluppatore digita nella pagina di verifica /device è di 8 caratteri tratti da un alfabeto di 20 caratteri, che produce 20⁸ o circa 2,56×10¹⁰ combinazioni, e scade dopo 10 minuti.
Il gateway applica limiti di velocità per IP sugli endpoint di concessione del dispositivo, configurabili tramite rate_limits. Aumenta i limiti se molti sviluppatori accedono da un singolo indirizzo NAT aziendale condiviso. I rollout su larga scala mostra come dimensionarli. I limiti si applicano solo al flusso di accesso, non all’inferenza.
Postura di conformità
- Residenza dei dati: il piano dati del gateway stesso non invia nulla ad Anthropic a meno che l’API Anthropic non sia un upstream configurato; quando lo è, il tuo accordo di gestione dei dati esistente si applica al percorso di inferenza. Telemetria, audit, identità e impostazioni vanno solo alle destinazioni che configuri.
- Traffico del processo host: il processo host è il Claude Code CLI. Il
claude gatewayviene eseguito secondo le stesse regole di terze parti delle distribuzioni Amazon Bedrock e Google Cloud’s Agent Platform e non invia nulla ad Anthropic. Prima della v2.1.227, il processo host inviava telemetria di avvio come versione del prodotto e piattaforma, che l’impostazione diCLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1nell’ambiente del container disattivava. Quelle versioni inviavano anche una richiestaHEADall’avvio, senza corpo o credenziali, a/api/hellosuhttps://api.anthropic.com, o suANTHROPIC_BASE_URLquando l’ambiente lo impostava, a meno che l’ambiente non impostasse anche una variabile proxy comeHTTPS_PROXYo un certificato client mTLS. Ignoravano la risposta, quindi bloccare quella richiesta al firewall di uscita non influenzava il gateway. - Analitiche client: il CLI disabilita la sua stessa analittica di utilizzo e segnalazione degli errori mentre è connesso a un gateway. Prima del primo accesso, il CLI invia comunque eventi di avvio ad Anthropic, incluso su macchine le cui impostazioni gestite forzano l’accesso al gateway. Per disattivare anche quelli, fornisci
DISABLE_TELEMETRYnelle stesse impostazioni gestite lato client che forzano l’accesso al gateway. - Segnalazione degli errori: il CLI disattiva la segnalazione degli errori ogni volta che le sue richieste di modello vanno a qualsiasi endpoint diverso dall’API di prima parte di Anthropic, come Amazon Bedrock o un
ANTHROPIC_BASE_URLpersonalizzato. - Macchine client: i CLI degli sviluppatori inviano comunque controlli del nome host WebFetch e controlli della versione ad Anthropic a meno che
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1eskipWebFetchPreflight: truenon siano impostati. Le richieste ai marketplace dei plugin hanno i propri interruttori di disattivazione. Consulta utilizzo dei dati. - Valutazioni del sondaggio: mentre è connesso a un gateway, il CLI disabilita il caricamento della valutazione legato ad Anthropic insieme ai flussi di analitiche, quindi non invia valutazioni ad Anthropic.
- Condivisione della trascrizione: scegliere Sì su un prompt di condivisione della trascrizione di un sondaggio scrive un file locale sotto
~/.claude/feedback-bundles/invece di caricare su Anthropic. - Aggiornamenti client: i controlli di aggiornamento sono separati dal traffico del gateway. Fissa le versioni attraverso la tua distribuzione e imposta
DISABLE_UPDATESse i laptop non devono recuperare le versioni.DISABLE_AUTOUPDATERinterrompe solo gli aggiornamenti in background mentreclaude updatefunziona ancora. - TLS: servi
public_urlsu HTTPS in produzione, sia dal listener proprio del gateway tramitelisten.tlsche da un ingress che termina TLS davanti alle repliche HTTP semplici, conlisten.public_urlimpostato in entrambi i casi. Il gateway non rifiuta HTTP semplice. L’IdP deve servire HTTPS in produzione, e Postgres supporta?sslmode=require. ImpostaStrict-Transport-Securityal tuo ingress. - Divulgazione di vulnerabilità: segui Segnalazione di problemi di sicurezza
Richieste ai marketplace dei plugin
Claude Code recupera i marketplace dei plugin direttamente dalla macchina di ogni sviluppatore, non attraverso il gateway. Requisiti di accesso alla rete elenca gli host. La prima volta che uno sviluppatore avvia una sessione interattiva nel terminale, Claude Code registra il marketplace ufficiale,claude-plugins-official. Scarica il catalogo da downloads.claude.ai e, se l’operazione non riesce, lo clona da github.com. Quali marketplace e plugin si aggiornano automaticamente tratta gli aggiornamenti successivi.
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 non impedisce la prima registrazione. Una qualsiasi di queste impostazioni gestite invece sì:
- Un elenco di marketplace: un’allowlist
strictKnownMarketplacesche esclude il marketplace, oppure una voceblockedMarketplacesche lo nomina - Una variabile d’ambiente:
CLAUDE_CODE_DISABLE_OFFICIAL_MARKETPLACE_AUTOINSTALLimpostata su"1"nel bloccoenvgestito
cli o code della policy del gateway.
Risoluzione dei problemi
Per domande e feedback, utilizza il supporto Claude Code, oppure apri un problema nel repository GitHub di Claude Code. Puoi anche contattare il team del tuo account Anthropic. Quando segnali un problema, includi:- Gateway issue: lo stderr del gateway per la finestra rilevante, il tuo
gateway.yamlcon i segreti oscurati, la versione del gateway, mostrata nella pagina di destinazione in/e nell’intestazione della rispostax-cc-gateway-versionin/managed/settings, e cosa è cambiato di recente - Login issue: lo sviluppatore esegue
claude --debug-file ./claude-debug.txt, riproduce il problema e invia quel file più il log di audit del gateway per la stessa finestra - Inference issue: il modello richiesto, gli upstream configurati e il log di audit del gateway per la richiesta, che registra quale upstream l’ha servita e lo stato della risposta
Il messaggio
Cloud gateway sign-in was not completed nomina il nome host del gateway. Quando Claude Code ha sia l’impronta digitale fissata che quella presentata, il messaggio mostra anche i primi 16 caratteri di ciascuna.
Se Claude Code segnala couldn't load your organization's managed settings dopo un accesso al gateway, Claude Code nomina il motivo, si riavvia sul posto e riprende la conversazione. Se Claude Code non può riavviarsi, ad esempio in una sessione in background, Claude Code termina la sessione e mantiene l’accesso.
Intestazioni della richiesta troppo grandi dopo l’accesso
Le richieste di uno sviluppatore possono fallire con un errore431 dopo l’accesso quando lo sviluppatore appartiene a molti gruppi IdP.
Il gateway risponde 431 quando le intestazioni di una richiesta superano in totale 256 KiB, oppure limits.max_request_header_bytes se lo imposti. Non scrive alcuna riga di log né evento di audit per queste richieste. Le versioni del gateway precedenti a v2.1.284 rispondono 431 oltre i 16 KiB.
Inizia dalla prima di queste opzioni che si applica al tuo gateway:
- Gateway precedente a v2.1.284: aggiorna il gateway
limits.max_request_header_bytesimpostato: aumenta il valore o rimuovi la chiave- Nessuno dei due casi si applica, oppure il
431continua in seguito: fai in modo che il tuo IdP emetta meno gruppi. Identity provider setup spiega come Okta, Microsoft Entra ID e Google Workspace forniscono i gruppi
oidc.allowed_groups: determina chi può accedereadmin.admin_groups: determina chi può chiamare l’API di amministrazione con la propria sessione del gatewaymatch.groupsinmanaged.policies: determina quale criterio si applica a uno sviluppatoregroupssu un upstream: determina quali upstream servono uno sviluppatorerbac_grouplimiti di spesa: determinano quali limiti di spesa di gruppo si applicano a uno sviluppatore
Il ragionamento lungo termina con timeout del proxy
Se il tuo upstream èprovider: anthropic, consulta invece Ragionamento lungo su un upstream Anthropic API: anche lì aumenti CLAUDE_STREAM_IDLE_TIMEOUT_MS, ma i tempi e gli errori sono diversi.
Se i turni falliscono dopo un ragionamento lungo e il tuo proxy registra una richiesta aperta per circa 12,5 minuti, poi una serie di errori 504, aumenta CLAUDE_STREAM_IDLE_TIMEOUT_MS in un criterio del gateway. Ad esempio, con un timeout di inattività di 240 secondi sul proxy, la serie è di 10 richieste, ciascuna interrotta a 240 secondi.
- La prima richiesta: uno stream che consegna il suo primo evento di risposta,
message_start, e poi solo ping mentre Claude ragiona. Con le impostazioni predefinite, Claude Code termina quello stream dopo circa 12,5 minuti. - Le altre 10: la stessa richiesta, inviata senza streaming e poi riprovata, 10 invii in tutto per impostazione predefinita. Non ricevono ping, quindi una risposta lenta raggiunge il timeout del proxy.
Conferma la causa
Chiedi a uno sviluppatore di riprodurre l’errore conclaude --debug-file ./claude-debug.txt, poi cerca in quel file questa riga:
CLAUDE_CODE_DISABLE_NONSTREAMING_FALLBACK su 1, non vedi richieste senza streaming, e il turno termina con API Error: Stream idle timeout - no chunks received. Si applica la stessa correzione.
Scegli un valore
Scegli un valore diCLAUDE_STREAM_IDLE_TIMEOUT_MS la cui seconda colonna copra la tua pausa di ragionamento più lunga, oppure inizia con 1800000 se non la conosci. Uno stream può restare con i soli ping per circa 7,5 minuti più del valore:
Se un upstream si blocca mentre il gateway continua a inviare ping, anche i tuoi sviluppatori attendono così a lungo prima che Claude Code rinunci allo stream. Una connessione che diventa completamente silenziosa termina comunque dopo 5-6 minuti, perché il timeout di inattività del corpo non segue questa variabile.
Distribuisci il valore in un criterio
Aggiungi la voceenv a ogni criterio in gateway.yaml che già distribuisce le impostazioni di Claude Code agli sviluppatori che vuoi coprire. Inseriscila sotto la chiave code, cli o settings che quel criterio ha già. Per provare prima il valore, inizia con un criterio che corrisponde a un solo gruppo. Vedi managed per sapere come i criteri corrispondono ed ereditano. Questo esempio aggiunge la voce a un criterio match: {} con chiave cli:
cli, copri le sessioni del terminale, dell’estensione IDE e dell’Agent SDK. Per la scheda Code di Claude Desktop, vedi Scegliere cli o code.
Riavvia il gateway in modo che legga il file modificato. Poi chiedi agli sviluppatori di riavviare Claude Code per ricevere CLAUDE_STREAM_IDLE_TIMEOUT_MS.
Ragionamento lungo su un upstream Anthropic API
Seprovider: anthropic è l’unico upstream del modello e il tuo proxy registra una richiesta aperta per circa 20 minuti, poi errori 502 o 504, aumenta CLAUDE_STREAM_IDLE_TIMEOUT_MS in un criterio del gateway.
- La richiesta lunga: uno stream che consegna
message_starte poi solo ping mentre Claude ragiona. Claude Code lo termina dopo circa 20 minuti con le impostazioni predefinite, e più tardi una volta che aumenti la variabile. - Gli errori: richieste che Claude Code invia poi senza streaming. Ciascuna fallisce con un
502dal gateway, oppure con il504del tuo proxy se il timeout del proxy è più breve dell’attesa del gateway. Quell’attesa ètimeouts.upstream_ttfb_ms, che non hai bisogno di aumentare per questa correzione.
900000 e 45 con 1800000. Poi segui Distribuisci il valore in un criterio.
Correlati
- Panoramica del gateway delle app Claude: quickstart e connessione dello sviluppatore
- Riferimento di configurazione: ogni opzione di
gateway.yaml