claude-code
claude-sniff перехватывает запросы Claude Code к Bedrock
Claude News
claude-codeРазработчик выложил на Show HN claude-sniff, локальный MitM-прокси, который встаёт между Claude Code и Amazon Bedrock и держит каждый перехваченный вызов до решения оператора: отправить дальше с переподписью SigV4 или сбросить. Код и инструкция опубликованы на Github; подмена ANTHROPIC_BASE_URL здесь не используется, поскольку Claude Code на Bedrock такой режим не поддерживает.
Коротко
- Слушатель поднимается на 127.0.0.1:9090, интерфейс на 127.0.0.1:8765; при первом запуске в ~/.mitmproxy записывается CA-сертификат mitmproxy, который Claude Code должен получить через четыре переменные окружения, после чего процесс claude нужно перезапустить.
- Перехваченные вызовы выстраиваются в общую очередь FIFO, редактировать можно только головной запрос: нетронутый JSON уходит в исходном виде без переподписи, изменённый переподписывается SigV4 из AWS-цепочки процесса.
- Стоимость считается по региональным on-demand ценам eu-central-1 и показывается в сайдбаре и по каждому запросу; неизвестная модель или профиль дают $0, а логи задним числом не переписываются.
Для команд, которые гоняют Claude Code через корпоративный аккаунт AWS, видимость того, что именно уходит в модель, обычно заканчивается на счетах Bedrock. Инструмент такого класса выглядит как способ посмотреть на системный промпт и полный контекст запроса до отправки, а заодно как стенд для экспериментов с телом вызова. Обратная сторона тоже очевидна: доверенный CA в системе и логи с промптами в открытом виде.
Очередь держит только вызовы Bedrock Runtime с заголовком x-claude-code-session-id
Перехват срабатывает на вызовах invoke и invoke-with-response-stream, в которых есть заголовок x-claude-code-session-id. Такой запрос останавливается, его головной JSON доступен для правки, после чего оператор нажимает Forward или Drop. Очередь глобальная и работает по принципу FIFO: редактируется только первый в ней запрос.
Нетронутое тело возобновляется в исходном виде и не переподписывается. Отредактированное уходит с новой подписью SigV4, взятой из AWS-цепочки процесса, который запустил main.py, поэтому для пересылки правленого тела нужно право InvokeModel на те же модели. Drop возвращает клиенту ошибку, пишет строку ошибки в JSONL и не обращается к Bedrock.
Выключение Intercept или Proxy сбрасывает очередь, и все удержанные запросы уходят в исходном виде. Сессия появляется во вкладке Sessions и на странице Proxy, пока она активна, а строки пишутся в файлы JSONL внутри каталога logs, разложенные по клиенту и идентификатору сессии.
Прокси и перехват выключены при старте и не сохраняются между запусками
Для запуска нужны Python 3.12+ и uv, Claude Code, реально ходящий в Bedrock Runtime с CLAUDE_CODE_USE_BEDROCK=1 в том же регионе и профиле, что и рабочая сессия, а также учётные данные AWS в процессе, который выполняет main.py. Слушатель поднимается на 127.0.0.1:9090, интерфейс на 127.0.0.1:8765.
Каждый новый процесс claude приходится настраивать отдельно: экспорт HTTP_PROXY и HTTPS_PROXY на порт 9090 не наследуется из другой оболочки. При выключенном Proxy трафик HTTPS просто туннелируется с настоящим сертификатом Bedrock, а вкладка Usage продолжает читать ~/.claude/projects. Интерфейс открывается на вкладке Sessions, переключатели Proxy и Intercept вынесены в шапку, причём Intercept недоступен, пока не включён Proxy.
После включения Proxy в ту же оболочку нужно добавить четыре переменные с путём к mitmproxy-ca-cert.pem: NODE_EXTRA_CA_CERTS, SSL_CERT_FILE, REQUESTS_CA_BUNDLE и AWS_CA_BUNDLE, и перезапустить claude. Автор советует доверять этому CA только на время, пока прокси включён. Ошибки TLS при включённом Proxy означают, что экспортов нет или процесс запущен раньше них.
Из строк JSONL вырезаются Authorization и x-amz-security-token, тела сохраняются как есть
Логи пишутся в каталог logs, который добавлен в gitignore. Из строк удаляются заголовки Authorization и x-amz-security-token, но тела, включая промпты и системную часть, сохраняются без изменений. Стоимость считается в момент чтения, поэтому поле costUSD задним числом в логи не дописывается.
Ценник берётся из региональных on-demand тарифов eu-central-1 и показывается в сайдбаре и по каждому запросу. Семейство модели определяется по ключевым словам в её имени либо по идентификаторам application-inference-profile, которые задаются переменной CLAUDE_PROXY_INFERENCE_PROFILES или файлом inference-profiles.json; сам репозиторий таких идентификаторов не содержит. Неизвестная модель или профиль дают $0.
Расходы дополняются журналами ~/.claude/projects: при совпадении UUID запись показывается один раз, приоритет у суммы из перехвата, а прямые строки идут только как стоимость, без переписки. Флаги меняют порты, каталоги логов и журналов, профиль AWS и отключают интерфейс; отдельная команда поднимает только UI, без MITM.
Чего claude-sniff не делает
Инструмент не работает как обратный прокси на ANTHROPIC_BASE_URL, не маскирует тела запросов и не перехватывает и не редактирует ответы Bedrock. Состояние переключателей Proxy и Intercept между запусками не сохраняется, готовых оверлеев для запросов и примеров джейлбрейков в репозитории нет. Если перехват ничего не держит, значит, это не вызов Bedrock invoke или в запросе нет заголовка сессии.
Комментарии
Пока никто не написал. Будьте первым.
Присоединяйтесь к разговору
Войдите через Google, чтобы оставить комментарий. Имя и аватар подставятся из вашего профиля Google, а комментарий появится после модерации.
Из Google мы используем только имя и аватар. Почту не сохраняем.
