インバウンドのクライアントトークン
デフォルトでは shunt にインバウンド認証はありません — ループバックのみの個人ゲートウェイなら問題ありませんが、VPN/トンネル越しに共有すると、そこに到達できる誰もが、マッピングされたモデルでオペレーターのアカウントを消費できてしまいます(shunt はそれらに自身の api_key/chatgpt_oauth 認証情報を注入します)。パススルーモデルは懸念ではありません。各呼び出し元自身の Anthropic 認証情報を転送します。
[server.auth] は、注入された認証情報を使うルートとモデル discovery を、クライアント単位トークンでゲートします。
[server.auth] # both keys optional; defaults shown
header = "x-shunt-token"
tokens_env = "SHUNT_CLIENT_TOKENS"# Gateway side: name:token pairs (names are labels for logging; tokens are secrets)
export SHUNT_CLIENT_TOKENS="minsu:$(openssl rand -hex 32),alice:$(openssl rand -hex 32)"起動は、[server.auth] が存在するのに環境変数が未設定または不正な場合、フェイルクローズします。有効なトークンなしでマッピングされたモデルや GET /v1/models へのリクエストは 401 authentication_error を受け取ります。どちらのゲートも、標準の Anthropic 認証情報スロットのいずれでもクライアントトークンを受け付けます — 複数のスロットに有効なトークンがある場合の優先順位は、設定されたヘッダー(デフォルト x-shunt-token)、次に Authorization: Bearer、次に x-api-key です。GET /routes、GET|HEAD /、GET /health、およびパススルーモデルは開いたままです。GET /routes はルーティングのメタデータ(設定されたプロバイダー/上流モデルのマッピング)を公開する shunt ネイティブのエンドポイントであるため未認証です — 認証情報は決して公開しません。認証情報はプロバイダー設定にのみ存在し、そのハンドラーによって読まれることはありません。
ゲートされたルートでは、受け付けられる認証情報ヘッダーは転送前に常に除去され(shunt はそこに自身のプロバイダー認証情報を注入します)、マッチングは定数時間で、トークン値はログに記録されません(クライアント名はリクエストごとに記録されます)。
クライアント側は、ゲートウェイが何を提供しているかで選びます。
-
プール/マッピング専用ゲートウェイ(例: Anthropic アカウントプールがデフォルトプロバイダー): クライアントトークンは、Claude Code がすでに送っている認証情報そのものにできます — 追加のヘッダー行は不要です。
export ANTHROPIC_AUTH_TOKEN="<your client token>" # Authorization: Bearer として送信される -
パススルーモデルが混在する場合:
Bearerスロットは各呼び出し元の実際の Anthropic 認証情報を運び続ける必要があるため、代わりに設定されたヘッダーで専用トークンを配布してください(ANTHROPIC_CUSTOM_HEADERSは 1 行ごとに 1 つのName: Valueを取ります)。export ANTHROPIC_CUSTOM_HEADERS="x-shunt-token: <your token>"
オプトインの管理 Web サーフェスも有効にする場合は、別個の管理トークンで保護し、HTTPS または信頼できるトンネル経由でのみ公開してください。
SSE キープアライブ ping
中間装置は静かなストリームを切断します — Cloudflare のプロキシは 1 バイトも来ないまま 100 秒で 524 を返し(Enterprise 未満では固定)、長い reasoning の合間はそれだけ静かになりえます。そのため shunt は、ストリーミングレスポンスがアイドルになるたびに、Anthropic プロトコル自身の ping イベント(api.anthropic.com 自身が発行し、すべてのクライアントが無視するもの)を注入します。
[server]
sse_keepalive_seconds = 30 # default; 0 disablesPing は完全な SSE イベントの間にのみ(半分送信されたフレームの内部には決して)、text/event-stream レスポンスにのみ注入され、上流ストリームと共に停止します。アイドルタイムアウトのないトンネル(WireGuard/Tailscale)の背後では ping は無害です。バイト単位で同一の中継が欲しい場合は 0 で無効化してください。