Перейти к содержимому
OmniRoute source

Stealth Guide (Русский)

Постоянные сеансы wreq-js создаются отложенно для каждой области учётной записи и разрешённого прокси. Общий для процесса пул TlsClient содержит не более 128 сеансов, которые имитируют Chrome 124 в macOS для вышестоящих сервисов, защищённых Cloudflare. TlsClient.fetch() завершает работу с ошибкой, если нативная среда выполнения недоступна; вызывающая сторона может явно выбрать резервный вариант вне этой обёртки.

  • Профиль сеанса: browser: "chrome_124", os: "macos"
  • Разрешение прокси (в порядке приоритета): HTTPS_PROXY → HTTP_PROXY → ALL_PROXY (также варианты в нижнем регистре)
  • Тайм-аут: TLS_CLIENT_TIMEOUT_MS (наследуется от FETCH_TIMEOUT_MS, по умолчанию 600000)
  • Ответ wreq-js совместим с fetch (headers, text(), json(), clone(), body).
  • Сторожевой таймер первого байта (open-sse/utils/tlsFirstByteWatchdog.ts, #12656): TlsClient.fetch() возвращает результат сразу после получения заголовков от вышестоящего сервиса, поэтому одного TLS_CLIENT_TIMEOUT_MS недостаточно для ограничения времени ожидания тела, которое так и не отдаёт первый байт. guardTlsFirstByte() запускает гонку между первым read() тела и TLS_FIRST_BYTE_WATCHDOG_MS (по умолчанию 10000, значение 0 отключает таймер); корректно работающий поток тела не затрагивается, а для зависшего потока чтение wreq отменяется, после чего существующая логика резервного TLS-подключения в proxyFetch переходит к прямому диспетчеру или диспетчеру прокси (запрос, повторное выполнение которого небезопасно, например POST с телом, всё равно завершается ошибкой, а не незаметно повторяется).
Заголовок раздела «Транспорт провайдеров с веб-cookie — wreq-js 3.2.0»

open-sse/services/tlsClientBase.ts — общий адаптер для пяти специализированных транспортов с веб-cookie, перечисленных ниже. Каждая тонкая обёртка провайдера выбирает профиль браузера и ОС. Адаптер использует единый загрузчик среды выполнения wreq и пул транспортов из open-sse/utils/tlsClient.ts, индексируемый по сочетанию профиля, ОС и разрешённого прокси, при этом каждый запрос использует cookieMode: "ephemeral". Таким образом, учётные записи и запросы совместно используют соединения транспортного уровня, но никогда не используют общий сеанс wreq или хранилище cookie.

Провайдер Профиль Эмулируемая ОС Политика EOF потока
Claude chrome_146 Linux включать [DONE]
Perplexity firefox_148 macOS включать event: end_of_stream
Grok chrome_146 Linux исключать [DONE]
Notion chrome_146 Windows включать [DONE]
LMArena chrome_146 Windows без маркера; закрывать при нативном EOF
  • При потоковой передаче нативный ReadableStream ответа используется напрямую; временный файл или вспомогательный процесс не создаётся.
  • До предоставления потока проверяются первые 256 байт. Провайдеры SSE буферизуют ошибки не в формате SSE; Grok/LMArena преобразуют проверочные страницы Cloudflare в 403, а промежуточные HTML-страницы — в 502.
  • Нативный тайм-аут запроса дополнительно ограничивается абсолютным жёстким сроком на стороне JS. При зависании аннулируется и закрывается только затронутый транспорт для соответствующего сочетания профиля, ОС и прокси; перед следующим запросом он создаётся заново.
  • Приоритет разрешения прокси: переданный для вызова proxyUrl → контекст учётной записи или панели управления в области запроса → HTTPS_PROXY/HTTP_PROXY/ALL_PROXY (включая варианты в нижнем регистре). Ошибки разрешения приводят к отказу без риска утечки через прямое соединение. LMArena намеренно выполняет разрешение относительно arena.ai.
  • byteResponse возвращает URL data: с указанием типа содержимого без повреждения UTF-8.
  • Возможные ошибки: TlsClientUnavailableError (пакет или дополнение недоступно), TlsClientHangError (превышен крайний срок) и WreqTransportCapacityError (общий код ошибки ёмкости сеансов), если все 128 ограниченных слотов для сочетаний профиля, ОС и прокси активны или находятся в процессе закрытия.

Описанный выше универсальный сеанс TlsClient остаётся специализированным для постоянного состояния cookie, поддерживаемого браузером. Оба пути повторно используют один кэшированный загрузчик модуля wreq и общий обработчик жизненного цикла процесса; их пулы остаются раздельными, поскольку сроки жизни cookie у них намеренно различаются.

Профили поддерживаются закреплённой версией пакета, однако фактическое принятие со стороны WAF может изменяться независимо от локальных контрактных тестов. Прежде чем заявлять о соответствии поведению вышестоящего браузера, проверяйте изменения цифровых отпечатков с использованием явно авторизованной действующей учётной записи.


Когда включён cliCompatMode, OmniRoute преобразует исходящие запросы Claude так, чтобы их нельзя было отличить от трафика claude-cli. Совместно работают три модуля:

Вычисляет 3-символьный отпечаток cc_version, встроенный в заголовок биллинга:

SHA256(SALT + msg[4] + msg[7] + msg[20] + version)[:3]
  • FINGERPRINT_SALT = "59cf53e54c78" (жёстко задано; соответствует официальному клиенту)
  • Входные данные: символы с индексами 4, 7 и 20 из текста первого сообщения пользователя + строка версии
  • Выходные данные: 3-символьный шестнадцатеричный префикс

Серверная проверка целостности, которую официальный CLI Claude Code вычисляет с помощью Bun/Zig. OmniRoute воспроизводит её с использованием xxhash-wasm:

  1. Сериализовать тело с заполнителем cch=00000;
  2. xxhash64(bytes, seed) & 0xFFFFF
  3. 5-символьное шестнадцатеричное значение в нижнем регистре с дополнением нулями
  4. Заменить cch=00000; вычисленным токеном

Константы:

  • Начальное значение: 0x6e52736ac806831e
  • Шаблон: /\bcch=([0-9a-f]{5});/

Вставляет Unicode-символ соединителя нулевой ширины (U+200D) после первого символа «чувствительных» имён клиентов, чтобы вышестоящие фильтры не могли обнаружить их с помощью grep. Список слов по умолчанию:

opencode, open-code, cline, roo-cline, roo_cline, cursor, windsurf,
aider, continue.dev, copilot, avante, codecompanion

Применяется к: блокам system, всему содержимому messages[].content, а также tools[].description / tools[].function.description. Оператор может переопределить список с помощью setSensitiveWords().

Для сторонних ретрансляторов Anthropic, принимающих только трафик «настоящего Claude Code»:

  • CLAUDE_CODE_COMPATIBLE_USER_AGENT = "claude-cli/2.1.258 (external, sdk-cli)"
  • CLAUDE_CODE_COMPATIBLE_STAINLESS_PACKAGE_VERSION = "0.112.1"
  • CLAUDE_CODE_COMPATIBLE_STAINLESS_RUNTIME_VERSION = "v26.3.0"
  • anthropic-beta = "claude-code-20250219,interleaved-thinking-2025-05-14,effort-2025-11-24" по умолчанию
  • Переключатель «Включить бета-версию редактирования рассуждений» для отдельного подключения добавляет redact-thinking-2026-02-12, когда вышестоящий сервис, совместимый с CC, явно требует потоки отредактированных рассуждений
  • Переключатель «Включить отображение сводки рассуждений» для отдельного подключения сохраняет providerSpecificData.requestDefaults.summarizeThinking и добавляет display: "summarized" к запросам рассуждений, совместимым с CC, если в них ещё не задан режим отображения
  • CONTEXT_1M_BETA_HEADER = "context-1m-2025-08-07" (семейство Opus/Sonnet 4.x)
  • Путь по умолчанию: /v1/messages?beta=true

Связанные модули в том же комплекте:

  • claudeCodeConstraints.ts — правила температуры и управления кешем
  • claudeCodeToolRemapper.ts — переназначение имён инструментов
  • claudeCodeExtraRemap.ts — дополнительная нормализация полезной нагрузки

Запросы Antigravity сохраняют текст вызывающей стороны побайтно. OmniRoute не вставляет в запросы символы нулевой ширины и не переименовывает/внедряет инструменты для имитации IDE-клиента.

Удаляет маркеры SDK Stainless (x-stainless-lang, x-stainless-package-version, x-stainless-os, x-stainless-arch, x-stainless-runtime, x-stainless-runtime-version, x-stainless-timeout, x-stainless-retry-count, x-stainless-helper-method) перед пересылкой.

⚠️ Риск: ANTIGRAVITY_CREDITS=always (основная причина блокировок аккаунтов)

Заголовок раздела «⚠️ Риск: ANTIGRAVITY_CREDITS=always (основная причина блокировок аккаунтов)»

ANTIGRAVITY_CREDITS=always (используется в open-sse/executors/antigravity.ts) направляет каждый запрос через платное превышение лимита кредитов Antigravity AI (платные кредиты Google), вместо того чтобы позволить квоте бесплатного уровня ограничивать использование. Это задокументировано как функция, но именно она является самой распространённой причиной сообщений о нарушении Условий использования, которые мы получаем — несколько аккаунтов Google Ultra были заблокированы с ошибкой 403 / "service disabled for ToS violation" / insufficient_quota после нескольких часов работы с =always.

Правила применяются на стороне Google, и OmniRoute никак не может этому помешать. Название переменной окружения и существующая документация создают впечатление, что эту настройку можно безопасно включить, однако это не так.

Почему это активнее вызывает обнаружение злоупотреблений, чем использование только бесплатного уровня:

  • Непрерывные автоматизированные расходы с одного аккаунта Google помечаются иначе, чем запросы бесплатного уровня, которые прекращаются после исчерпания квоты.
  • Для превышения лимита кредитов нет ограничения скорости, поэтому неправильно настроенный клиент может потратить несколько сотен USD за считаные минуты, создавая впечатление перепродажи API-ключей или трафика ботов.
  • Параллельное использование кредитов сверх лимита несколькими пользователями OmniRoute с одного внешнего IP усиливает этот сигнал.

Рекомендуемый подход:

  1. Сохраняйте значение по умолчанию ANTIGRAVITY_CREDITS=off, если оператор явно не принимает риски платных кредитов и принудительных мер в отношении аккаунта. retry сначала отправляет обычный запрос и добавляет кредиты не более одного раза после подходящей ошибки квоты 429; always добавляет кредиты уже в первый запрос.
  2. Распределяйте нагрузку между провайдерами с помощью Auto-Combo (model: "auto" или комбинаций kr/glm/etc), а не перегружайте один аккаунт Antigravity.
  3. Установите ограничения RPM для каждого подключения на странице редактирования провайдера Antigravity (Dashboard → Providers → Antigravity → подключение → ограничение частоты запросов). 30–60 RPM — обоснованный верхний предел для длительного использования.
  4. Используйте стабильную вышестоящую сеть под управлением оператора и не используйте один аккаунт совместно для несвязанных пользователей или рабочих нагрузок.
  5. В случае блокировки: подайте апелляцию через support.google.com → «Восстановить доступ к Workspace/аккаунту», приложив точное тело ответа quota_exceeded / service disabled, отправленного Google. Восстановление не гарантируется.

Справочник по переменным окружения описывает последствия каждого режима кредитов для аккаунта и расходов.

Точки интеграции:

  • open-sse/executors/antigravity.ts — считывает process.env.ANTIGRAVITY_CREDITS
  • src/lib/oauth/providers/antigravity.ts — передача учётных данных
  • Исходный отчёт об инциденте: обсуждение #1183

Реестр отпечатков CLI — open-sse/config/cliFingerprints.ts

Заголовок раздела «Реестр отпечатков CLI — open-sse/config/cliFingerprints.ts»

Таблица для каждого провайдера, фиксирующая точный порядок заголовков и полей тела JSON, полученный из трассировок mitmproxy официальных CLI. В настоящее время зарегистрированы: codex, claude, а также профили, формируемые во время выполнения в providerHeaderProfiles.ts для antigravity и github.

interface CliFingerprint {
headerOrder: string[]; // с учётом регистра
bodyFieldOrder: string[]; // ключи JSON верхнего уровня
userAgent?: string | (() => string);
extraHeaders?: Record<string, string>;
}

Переключается отдельно для каждого провайдера через переменные окружения (см. ниже). Если функция отключена, заголовки и ключи тела располагаются в том порядке, в котором их предоставили Node/JSON, — это упрощает создание отпечатка.


Для CLI, бинарные файлы которых нельзя перенаправить через OPENAI_BASE_URL, OmniRoute запускает локальный прокси-сервер с завершением TLS. Конечные точки находятся в src/app/api/cli-tools/antigravity-mitm/.

Метод Конечная точка Назначение
GET /api/cli-tools/antigravity-mitm Состояние — running, pid, dnsConfigured, certExists
POST /api/cli-tools/antigravity-mitm Запуск MITM (требуются apiKey и sudoPassword)
DELETE /api/cli-tools/antigravity-mitm Остановка MITM
GET /api/cli-tools/antigravity-mitm/alias Получение списка псевдонимов моделей
PUT /api/cli-tools/antigravity-mitm/alias Сохранение псевдонимов моделей для инструмента

Целевой перехватываемый хост: daily-cloudcode-pa.googleapis.com (вышестоящий сервер Antigravity).

Последовательность запуска (src/mitm/manager.ts::startMitm)

Заголовок раздела «Последовательность запуска (src/mitm/manager.ts::startMitm)»
  1. Создать самоподписанный сертификат с помощью selfsigned (RSA-2048, SHA-256, 1 год) — cert/generate.ts
  2. Установить сертификат в системное хранилище доверенных сертификатов — cert/install.ts
  3. Добавить в hosts запись 127.0.0.1 daily-cloudcode-pa.googleapis.com — dns/dnsConfig.ts
  4. Запустить src/mitm/server.cjs с ROUTER_API_KEY и MITM_LOCAL_PORT (по умолчанию 443)
  5. Сохранить PID в <DATA_DIR>/mitm/.mitm.pid

Динамическое обнаружение хранилища доверенных сертификатов Linux — cert/install.ts

Заголовок раздела «Динамическое обнаружение хранилища доверенных сертификатов Linux — cert/install.ts»

getLinuxCertConfig() проходит по списку приоритетов и выбирает первый существующий каталог:

Семейство дистрибутивов Каталог Команда обновления
Debian / Ubuntu /usr/local/share/ca-certificates update-ca-certificates
Arch / CachyOS / Manjaro /etc/ca-certificates/trust-source/anchors update-ca-trust
Fedora / RHEL / CentOS /etc/pki/ca-trust/source/anchors update-ca-trust
openSUSE /etc/pki/trust/anchors update-ca-certificates

Имя файла сертификата: omniroute-mitm.crt. Сопоставление отпечатка выполняется через getCertFingerprint() (SHA-1 от DER).

Кроме того, updateNssDatabases() устанавливает сертификат в пользовательские базы данных NSS, если доступен certutil: ~/.pki/nssdb, ~/snap/chromium/.../nssdb, все профили Firefox (включая snap), под именем OmniRoute MITM Root CA.

  • macOS: security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain
  • Windows: PowerShell с повышенными привилегиями → certutil -addstore Root

Все конечные точки MITM требуют управленческой аутентификации (requireCliToolsAuth). Пароль sudo кэшируется в области видимости модуля (но не в globalThis) и очищается при вызове stopMitm().


Переопределение User-Agent — переменные среды (.env.example, раздел 12)

Заголовок раздела «Переопределение User-Agent — переменные среды (.env.example, раздел 12)»
Переменная Значение по умолчанию
CLAUDE_USER_AGENT claude-cli/2.1.258 (external, cli)
CODEX_USER_AGENT codex-cli/0.155.0 (Windows 10.0.26200; x64)
GITHUB_USER_AGENT GitHubCopilotChat/0.54.0
ANTIGRAVITY_USER_AGENT antigravity/2.0.1 linux/arm64 google-api-nodejs-client/10.3.0
KIRO_USER_AGENT AWS-SDK-JS/3.0.0 kiro-ide/1.0.0
QODER_USER_AGENT Qoder-Cli
CURSOR_USER_AGENT Cursor/3.4

Используются в open-sse/executors/base.ts::buildHeaders() посредством динамического поиска. Обновляйте их при выпуске провайдерами новых версий CLI — устаревшие строки UA начинают отклоняться как принадлежащие устаревшим клиентам.

Переключатели режима совместимости с CLI (раздел 13 в .env.example)

Заголовок раздела «Переключатели режима совместимости с CLI (раздел 13 в .env.example)»
Переменная Эффект
CLI_COMPAT_CODEX=1 Отпечаток Codex
CLI_COMPAT_CLAUDE=1 Отпечаток claude-cli
CLI_COMPAT_GITHUB=1 Отпечаток GitHub Copilot Chat
CLI_COMPAT_ANTIGRAVITY=1 Отпечаток Antigravity
CLI_COMPAT_KIRO=1 Kiro
CLI_COMPAT_CURSOR=1 Cursor
CLI_COMPAT_KIMI_CODING=1 Kimi Coding
CLI_COMPAT_KILOCODE=1 KiloCode
CLI_COMPAT_CLINE=1 Cline
CLI_COMPAT_ALL=1 Включить всё перечисленное выше

IP-адрес провайдера всегда сохраняется — переключатель изменяет только сетевой образ запроса и не меняет исходящий IP-адрес.


Перед пересылкой OmniRoute очищает входящие клиентские заголовки, чтобы запрос, поступивший от Cursor, не передавал User-Agent: Cursor/X.Y.Z вышестоящему серверу Claude. Список запрещённых заголовков находится в src/shared/constants/upstreamHeaders.ts и синхронизируется со схемами Zod и модульными тестами.


Обновление отпечатков при их смене провайдером

Заголовок раздела «Обновление отпечатков при их смене провайдером»
  1. Перехватите трафик официального CLI с помощью mitmproxy (перехват TLS + дамп)
  2. Извлеките JA3/JA4 и точный порядок заголовков
  3. Обновите соответствующую запись CLI_FINGERPRINTS[...]
  4. Обновите соответствующее значение *_USER_AGENT по умолчанию в .env.example
  5. Если изменилось само рукопожатие TLS, обновите соответствующую обёртку провайдера или параметр browser: в wreq-js
  6. Запустите специфичные для провайдера тесты TLS и выполните ручную канареечную проверку на рабочем провайдере
  7. Выпустите патч-релиз и задокументируйте изменения в CHANGELOG.md

  • open-sse/services/__tests__/claudeTlsClient.test.ts — поведение общей обёртки TLS
  • tests/unit/anthropic-cache-fingerprint.test.ts — детерминированность отпечатка
  • tests/unit/chatgpt-web-source-retirement.test.ts — проверка того, что общий скрытый источник ChatGPT Web остаётся удалённым, а Codex Web — присутствует

  • RESILIENCE_GUIDE.md — что происходит, когда скрытый маршрут получает ответ 403
  • TROUBLESHOOTING.md
  • ENVIRONMENT.md — полный справочник переменных окружения
  • CLI-TOOLS.md — рабочий процесс MITM с точки зрения оператора

Исходный код OmniRoute (a58000c7685f)

HagiCode

HagiCode — агентная среда разработки со структурированными процессами, параллельным выполнением несколькими агентами и интерфейсами Hero Dungeon.

Превращайте идеи в полезное ПО с более умным, быстрым и увлекательным агентным рабочим процессом.

Главный экран HagiCode в светлой теме
  • SmartСтруктурированные процессы превращают намерение в исполнимый путь от идеи до готового изменения.
  • EfficientМультиагентные процессы параллельно продвигают исследование, реализацию и проверку.
  • FunHero Dungeon делает длительную совместную разработку наглядной и увлекательной.
Перейти на HagiCode