cc-gateway-ai-proxy

安装量: 239
排名: #8672

安装

npx skills add https://github.com/aradotso/trending-skills --skill cc-gateway-ai-proxy

CC Gateway — AI API Identity Gateway Skill by ara.so — Daily 2026 Skills collection. CC Gateway is a TypeScript reverse proxy that sits between Claude Code clients and the Anthropic API. It normalizes 40+ device fingerprint dimensions (device ID, email, environment, RAM, headers, and system prompt content) to a single canonical identity, manages OAuth token refresh centrally, and prevents telemetry leakage from multi-machine setups. Architecture Overview Client (Claude Code + env vars + Clash) └─► CC Gateway (rewrite + auth inject + SSE passthrough) └─► api.anthropic.com (single canonical identity) Gateway also contacts: platform.claude.com (OAuth token refresh only) Three-layer defense: Layer Mechanism Env vars Route CC traffic to gateway, disable side channels Clash rules Block any direct Anthropic connections at network level Gateway Rewrite all 40+ fingerprint dimensions in-flight Installation Prerequisites Node.js 18+ or Docker A machine that has previously logged into Claude Code (for OAuth token extraction) Clone and Install git clone https://github.com/motiful/cc-gateway.git cd cc-gateway npm install Generate Identity and Tokens

Create a stable canonical identity (device_id, email, env profile)

npm run generate-identity

Create a bearer token for a specific client machine

npm run generate-token my-laptop npm run generate-token work-desktop Extract OAuth Token (from a logged-in machine)

macOS — copies refresh_token from Keychain

bash scripts/extract-token.sh Configure cp config.example.yaml config.yaml Edit config.yaml :

config.yaml

identity : device_id : "GENERATED_DEVICE_ID"

from generate-identity

email : "canonical@example.com" platform : "darwin" arch : "arm64" node_version : "20.11.0" shell : "/bin/zsh" home : "/Users/canonical" working_directory : "/Users/canonical/projects" memory_gb : 16

canonical RAM value

oauth : refresh_token : "EXTRACTED_REFRESH_TOKEN"

from extract-token.sh

clients : - name : my - laptop token : "GENERATED_CLIENT_TOKEN" - name : work - desktop token : "ANOTHER_CLIENT_TOKEN" server : port : 8443 tls : false

true for production with certs

Starting the Gateway

Development (no TLS, hot reload)

npm run dev

Production build

npm run build && npm start

Docker Compose (recommended for production)

docker-compose up -d Docker Compose Example

docker-compose.yml

version : "3.8" services : cc-gateway : build : . ports : - "8443:8443" volumes : - ./config.yaml : /app/config.yaml : ro restart : unless - stopped environment : - NODE_ENV=production Verification

Health check

curl http://localhost:8443/_health

Show before/after rewrite diff (requires client token)

curl -H "Authorization: Bearer YOUR_CLIENT_TOKEN" \ http://localhost:8443/_verify Client Machine Setup On each machine running Claude Code, set these environment variables:

~/.bashrc or ~/.zshrc

Route all Claude Code API traffic through the gateway

export ANTHROPIC_BASE_URL = "https://gateway.your-domain.com:8443"

Disable side-channel telemetry (Datadog, GrowthBook, version checks)

export CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC = 1

Skip browser OAuth — gateway handles authentication

export CLAUDE_CODE_OAUTH_TOKEN = "gateway-managed"

Authenticate to the gateway with the per-machine token

export ANTHROPIC_CUSTOM_HEADERS = "Proxy-Authorization: Bearer YOUR_CLIENT_TOKEN" Or use the interactive setup script: bash scripts/client-setup.sh Then just run claude — no login prompt required. Clash Rules (Network-Level Blocking) Add to your Clash configuration to block any direct Anthropic connections:

clash-rules.yaml excerpt

rules : - DOMAIN , gateway.your - domain.com , DIRECT

Allow your gateway

- DOMAIN - SUFFIX , anthropic.com , REJECT

Block direct API calls

- DOMAIN - SUFFIX , claude.com , REJECT

Block direct OAuth

- DOMAIN - SUFFIX , claude.ai , REJECT

Block Claude web

- DOMAIN - SUFFIX , datadoghq.com , REJECT

Block Datadog telemetry

- DOMAIN - SUFFIX , statsig.com , REJECT

Block feature flags

See clash-rules.yaml in the repo for the full template. What Gets Rewritten Layer Field Transformation Identity device_id → canonical ID from config Identity email → canonical email Environment env object (40+ fields) → entire object replaced Process constrainedMemory (physical RAM) → canonical value Process rss , heapTotal , heapUsed → randomized in realistic range Headers User-Agent → canonical CC version string Headers Authorization → real OAuth token (injected) Headers x-anthropic-billing-header → canonical fingerprint Prompt text Platform , Shell , OS Version → canonical values Prompt text /Users/xxx/ , /home/xxx/ → canonical home prefix Leak fields baseUrl → stripped Leak fields gateway provider field → stripped TypeScript Usage Examples Custom Rewriter Extension // src/rewriters/custom-field-rewriter.ts import { RequestRewriter } from '../types' ; export const customFieldRewriter : RequestRewriter = { name : 'custom-field-rewriter' , rewriteBody ( body : Record < string , unknown

, config : CanonicalConfig ) : Record < string , unknown

{ // Strip any custom analytics fields your org adds const { __analytics , __session_debug , ... cleaned } = body as any ; // Normalize any additional identity fields if ( cleaned . metadata ?. user_id ) { cleaned . metadata . user_id = config . identity . device_id ; } return cleaned ; } , rewriteHeaders ( headers : Record < string , string

, config : CanonicalConfig ) : Record < string , string

{ return { ... headers , 'x-custom-client' : 'canonical' , } ; } } ; Programmatic Gateway Start // scripts/start-with-monitoring.ts import { createGateway } from '../src/gateway' ; import { loadConfig } from '../src/config' ; async function main ( ) { const config = await loadConfig ( './config.yaml' ) ; const gateway = await createGateway ( config ) ; gateway . on ( 'request' , ( { clientId , path } ) => { console . log ( [ ${ new Date ( ) . toISOString ( ) } ] ${ clientId } → ${ path } ) ; } ) ; gateway . on ( 'rewrite' , ( { field , before , after } ) => { console . log ( Rewrote ${ field } : ${ before } → ${ after } ) ; } ) ; gateway . on ( 'tokenRefresh' , ( { expiresAt } ) => { console . log ( OAuth token refreshed, expires: ${ expiresAt } ) ; } ) ; await gateway . listen ( config . server . port ) ; console . log ( Gateway running on port ${ config . server . port } ) ; } main ( ) . catch ( console . error ) ; Token Generation (Programmatic) // scripts/provision-client.ts import { generateClientToken , addClientToConfig } from '../src/auth' ; async function provisionNewMachine ( machineName : string ) { const token = await generateClientToken ( machineName ) ; await addClientToConfig ( './config.yaml' , { name : machineName , token , created_at : new Date ( ) . toISOString ( ) , } ) ; console . log ( Client token for ${ machineName } : ) ; console . log ( token ) ; console . log ( '\nAdd to client machine:' ) ; console . log ( export ANTHROPIC_CUSTOM_HEADERS="Proxy-Authorization: Bearer ${ token } " ) ; } provisionNewMachine ( process . argv [ 2 ] ?? 'new-machine' ) ; Key npm Scripts Command Purpose npm run dev Start with hot reload (development) npm run build Compile TypeScript to dist/ npm start Run compiled production build npm test Run rewriter test suite (13 tests) npm run generate-identity Create canonical device profile npm run generate-token Create per-client bearer token Common Patterns Multiple Machines, One Identity

On gateway server — generate once

npm run generate-identity

→ device_id: abc-123, email: canonical@proxy.local

Provision each machine

npm run generate-token laptop-home

→ token-aaa

npm run generate-token laptop-work

→ token-bbb

npm run generate-token desktop

→ token-ccc

All three machines present as the same device to Anthropic

Rotating the Canonical Identity

Generate a new identity (e.g., after a suspected flag)

npm run generate-identity --force

Update config.yaml with new device_id

Restart gateway — all clients immediately use new identity

docker-compose restart cc-gateway Checking for New Telemetry Fields After CC Updates

After a Claude Code update, use _verify to diff

curl -H "Authorization: Bearer $TOKEN " \ http://localhost:8443/_verify | jq '.unrewritten_fields'

Monitor Clash logs for new endpoints

Any REJECT hits on new domains = new hardcoded endpoints

Troubleshooting claude still prompts for browser login Ensure CLAUDE_CODE_OAUTH_TOKEN=gateway-managed is exported Verify ANTHROPIC_BASE_URL points to your running gateway Check gateway logs: docker-compose logs -f cc-gateway 401 Unauthorized from gateway Confirm ANTHROPIC_CUSTOM_HEADERS contains Proxy-Authorization: Bearer Verify the token in config.yaml matches the one set in env var Run curl -H "Authorization: Bearer $TOKEN" http://localhost:8443/_health OAuth token expired

Re-extract from a logged-in machine

bash scripts/extract-token.sh

Paste new refresh_token into config.yaml

docker-compose restart cc-gateway MCP servers bypassing gateway MCP uses mcp-proxy.anthropic.com which ignores ANTHROPIC_BASE_URL . Add to Clash: - DOMAIN , mcp - proxy.anthropic.com , REJECT Requests reaching Anthropic directly (Clash not blocking) Check Clash is running: clash -v Verify rules are loaded: look for REJECT entries in Clash dashboard Test: curl https://api.anthropic.com — should fail if Clash is active Gateway rewrite not applying to a new field After a Claude Code update, new telemetry fields may not be covered. Check /_verify for unrewritten_fields , then open an issue or add a custom rewriter (see Custom Rewriter Extension above). Caveats MCP servers — hardcoded endpoint, use Clash to block if not needed CC updates — monitor Clash REJECT logs after every Claude Code update for new endpoints Refresh token lifetime — if the OAuth refresh token expires, re-run extract-token.sh ToS — do not use for account sharing; intended for managing your own devices under one subscription Alpha — test with a non-primary account before production use

返回排行榜