콘텐츠로 이동
OmniRoute source

Stealth Guide (한국어)

open-sse/utils/tlsClient.ts — wreq-js (Chrome 124)

섹션 제목: “open-sse/utils/tlsClient.ts — wreq-js (Chrome 124)”

영구 wreq-js 세션은 계정 범위 및 확인된 프록시별로 지연 생성됩니다. 프로세스 전역 TlsClient는 Cloudflare 뒤에 있는 업스트림을 대상으로 macOS의 Chrome 124를 가장하는 세션을 최대 128개까지 풀링합니다. 네이티브 런타임을 사용할 수 없으면 TlsClient.fetch()는 실패 시 차단되며, 호출자는 이 래퍼 외부에서 폴백을 명시적으로 선택할 수 있습니다.

  • 세션 프로필: browser: "chrome_124", os: "macos"
  • 프록시 확인(우선순위): HTTPS_PROXY → HTTP_PROXY → ALL_PROXY(소문자 변수도 포함)
  • 시간 제한: TLS_CLIENT_TIMEOUT_MS(FETCH_TIMEOUT_MS에서 상속, 기본값 600000)
  • wreq-js Response는 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 리더를 취소하고 proxyFetch의 기존 TLS 폴백 로직이 직접/프록시 디스패처로 넘어가도록 합니다(예: 본문이 있는 POST처럼 재실행이 안전하지 않은 요청은 자동으로 재시도되지 않고 여전히 예외를 발생시킵니다).

웹 쿠키 제공자 전송 계층 — wreq-js 3.2.0

섹션 제목: “웹 쿠키 제공자 전송 계층 — wreq-js 3.2.0”

open-sse/services/tlsClientBase.ts는 아래의 특수 웹 쿠키 전송 계층 5개가 공유하는 어댑터입니다. 각 경량 제공자 래퍼는 브라우저/OS 프로필을 선택합니다. 어댑터는 open-sse/utils/tlsClient.ts의 단일 wreq 런타임 로더와 전송 풀을 사용하며, 프로필 + OS + 확인된 프록시를 키로 사용합니다. 한편 모든 요청은 cookieMode: "ephemeral"을 사용합니다. 따라서 계정과 요청은 전송 계층 연결을 공유하지만, wreq 세션이나 쿠키 저장소는 절대 공유하지 않습니다.

제공자 프로필 에뮬레이션 OS 스트림 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 하드 데드라인으로 계속 래핑됩니다. 중단이 발생하면 영향을 받은 프로필/OS/프록시 전송 계층만 무효화하고 닫으며, 다음 요청 전에 이를 다시 생성합니다.
  • 프록시 확인 우선순위는 호출별 proxyUrl → 요청 범위의 계정/대시보드 컨텍스트 → HTTPS_PROXY/HTTP_PROXY/ALL_PROXY(소문자 변수 포함)입니다. 확인 오류 시 직접 연결이 누출되지 않도록 실패 시 차단됩니다. LMArena는 의도적으로 arena.ai를 기준으로 확인합니다.
  • byteResponse는 UTF-8 손상 없이 콘텐츠 유형이 지정된 data: URL을 반환합니다.
  • 모든 128개의 제한된 프로필/OS/프록시 슬롯이 사용 중이거나 닫히는 중일 때 발생하는 오류는 TlsClientUnavailableError(패키지/애드온 사용 불가), TlsClientHangError(데드라인 초과), WreqTransportCapacityError(공유 세션 용량 오류 코드)입니다.

위의 범용 TlsClient 세션은 브라우저 기반의 영구 쿠키 상태에 계속 특화되어 있습니다. 두 경로 모두 캐시된 단일 wreq 모듈 로더와 프로세스 수명 주기 훅을 재사용하지만, 의도된 쿠키 수명이 서로 다르므로 각 풀은 분리된 상태로 유지됩니다.

이 프로필들은 고정된 패키지에서 지원되지만, 실제 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자의 16진수 접두사

claudeCodeCCH.ts (클라이언트 콘텐츠 해시)

섹션 제목: “claudeCodeCCH.ts (클라이언트 콘텐츠 해시)”

공식 Claude Code CLI가 Bun/Zig를 통해 계산하는 서버 측 무결성 검사입니다. OmniRoute는 이를 xxhash-wasm으로 재구현합니다.

  1. cch=00000; 자리표시자를 사용하여 본문 직렬화
  2. xxhash64(bytes, seed) & 0xFFFFF
  3. 0으로 채운 5자의 소문자 16진수
  4. cch=00000;을 계산된 토큰으로 교체

상수:

  • 시드: 0x6e52736ac806831e
  • 패턴: /\bcch=([0-9a-f]{5});/

업스트림 필터가 “민감한” 클라이언트 이름을 grep으로 검색하지 못하도록 해당 이름의 첫 번째 문자 뒤에 유니코드 폭 없는 결합자(U+200D)를 삽입합니다. 기본 단어 목록:

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()를 통해 재정의할 수 있습니다.

claudeCodeCompatible.ts — anthropic-compatible-cc-* 제공자

섹션 제목: “claudeCodeCompatible.ts — anthropic-compatible-cc-* 제공자”

“실제 Claude Code” 트래픽만 허용하는 서드파티 Anthropic 릴레이용입니다.

  • 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"
  • 연결별 “Enable redact-thinking beta” 토글은 CC Compatible 업스트림에서 수정된 사고 스트림이 특별히 필요한 경우 redact-thinking-2026-02-12를 추가합니다.
  • 연결별 “Enable summarized thinking display” 토글은 providerSpecificData.requestDefaults.summarizeThinking을 저장하고, 아직 표시 모드가 설정되지 않은 CC Compatible 사고 요청에 display: "summarized"를 추가합니다.
  • CONTEXT_1M_BETA_HEADER = "context-1m-2025-08-07"(Opus/Sonnet 4.x 제품군)
  • 기본 경로: /v1/messages?beta=true

동일한 번들에 포함된 관련 모듈:

  • claudeCodeConstraints.ts — temperature + cache-control 규칙
  • claudeCodeToolRemapper.ts — 도구 이름 재매핑
  • claudeCodeExtraRemap.ts — 추가 페이로드 정규화

Antigravity 요청은 호출자의 텍스트를 바이트 단위로 그대로 보존합니다. OmniRoute는 IDE 클라이언트를 모방하기 위해 프롬프트에 폭 없는 문자를 삽입하거나 도구 이름을 변경/주입하지 않습니다.

전달하기 전에 Stainless SDK 마커(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에서 사용)는 Google의 무료 등급 할당량이 요청을 제한하도록 두는 대신 모든 요청을 Antigravity AI Credit Overages(유료 Google 크레딧)를 통해 라우팅합니다. 이는 기능으로 문서화되어 있지만, 현재 가장 자주 보고되는 단일 ToS 위반 사례입니다. 여러 Google Ultra 계정이 =always로 몇 시간 실행한 후 403 / "service disabled for ToS violation" / insufficient_quota와 함께 정지되었습니다.

업스트림 집행은 OmniRoute가 방지할 수 있는 것이 아니라 Google 측에서 이루어집니다. 환경 변수 이름과 기존 문서만 보면 안전하게 활성화할 수 있는 설정처럼 보이지만, 실제로는 그렇지 않습니다.

무료 등급만 사용하는 경우보다 악용 감지에 더 적극적으로 포착되는 이유:

  • 단일 Google 계정에서 지속적으로 자동화된 지출이 발생하면, 무료 등급의 할당량에 도달하여 중지되는 경우와는 다른 방식으로 표시됩니다.
  • 크레딧 초과 사용에는 속도 상한이 없으므로, 잘못 구성된 클라이언트가 몇 분 만에 수백 USD를 소진하고 API 키 재판매나 봇 트래픽처럼 보일 수 있습니다.
  • 여러 OmniRoute 사용자가 동일한 외부 IP에서 동시에 초과 사용 크레딧을 소비하면 탐지 신호가 누적됩니다.

권장 운영 방침:

  1. 운영자가 유료 크레딧 및 계정 집행 위험을 명시적으로 수락하지 않는 한 기본값인 ANTIGRAVITY_CREDITS=off를 유지하세요. retry는 먼저 일반 요청을 전송하고, 해당되는 할당량 429가 발생한 후 최대 한 번만 크레딧을 주입합니다. always는 첫 번째 요청부터 크레딧을 주입합니다.
  2. 단일 Antigravity 계정을 포화시키는 대신 Auto-Combo를 통해 제공자 전체에 부하를 분산하세요(model: "auto" 또는 kr/glm/etc-combo).
  3. Antigravity 제공자의 편집 페이지(Dashboard → Providers → Antigravity → connection → rate limit)에서 연결별 RPM 제한을 설정하세요. 지속적인 사용에는 30~60 RPM이 합리적으로 방어 가능한 상한입니다.
  4. 운영자가 제어하는 안정적인 업스트림 네트워크를 사용하고, 서로 관련 없는 사용자나 워크로드가 하나의 계정을 공유하지 않도록 하세요.
  5. 정지된 경우: Google이 전송한 정확한 quota_exceeded / service disabled 응답 본문과 함께 support.google.com → “Restore Workspace/Account access”를 통해 이의를 제기하세요. 복구는 보장되지 않습니다.

환경 참조 문서에는 각 크레딧 모드가 계정과 지출에 미치는 영향이 설명되어 있습니다.

관련 지점:

  • open-sse/executors/antigravity.ts — process.env.ANTIGRAVITY_CREDITS를 읽음
  • src/lib/oauth/providers/antigravity.ts — 자격 증명 연결 처리
  • 최초 사고 보고서: Discussion #1183

CLI 핑거프린트 레지스트리 — open-sse/config/cliFingerprints.ts

섹션 제목: “CLI 핑거프린트 레지스트리 — open-sse/config/cliFingerprints.ts”

공식 CLI의 mitmproxy 트레이스에서 캡처한 정확한 헤더 순서와 JSON 본문 필드 순서를 고정하는 공급자별 테이블입니다. 현재 등록된 항목은 codex, claude이며, antigravity와 github의 경우 providerHeaderProfiles.ts에서 런타임에 파생된 프로필도 포함됩니다.

interface CliFingerprint {
headerOrder: string[]; // 대소문자 구분
bodyFieldOrder: string[]; // 최상위 JSON 키
userAgent?: string | (() => string);
extraHeaders?: Record<string, string>;
}

환경 변수를 통해 공급자별로 전환합니다(아래 참조). 비활성화하면 헤더/본문 키는 Node/JSON이 제공한 순서대로 표시되므로 핑거프린팅하기 쉽습니다.


MITM 프록시(Antigravity, Linux/macOS/Windows)

섹션 제목: “MITM 프록시(Antigravity, Linux/macOS/Windows)”

바이너리를 OPENAI_BASE_URL을 통해 리디렉션할 수 없는 CLI를 위해 OmniRoute는 로컬 TLS 종단 프록시를 실행합니다. 엔드포인트는 src/app/api/cli-tools/antigravity-mitm/ 아래에 있습니다.

메서드 엔드포인트 용도
GET /api/cli-tools/antigravity-mitm 상태 — 실행 여부, 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. ROUTER_API_KEY + MITM_LOCAL_PORT(기본값 443)를 사용하여 src/mitm/server.cjs 실행
  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()를 통해 핑거프린트를 일치시킵니다(DER의 SHA-1).

또한 certutil을 사용할 수 있는 경우 updateNssDatabases()는 사용자별 NSS DB인 ~/.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 호환성 모드 토글 (.env.example 섹션 13)

섹션 제목: “CLI 호환성 모드 토글 (.env.example 섹션 13)”
변수 효과
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 업스트림에 노출되지 않도록 합니다. Zod 스키마 및 단위 테스트와 동기화된 거부 목록은 src/shared/constants/upstreamHeaders.ts를 참조하세요.


공급자가 핑거프린트를 변경할 때 업데이트하기

섹션 제목: “공급자가 핑거프린트를 변경할 때 업데이트하기”
  1. mitmproxy로 공식 CLI 트래픽 캡처(TLS 가로채기 + 덤프)
  2. JA3/JA4 및 실제 헤더 순서 추출
  3. 관련 CLI_FINGERPRINTS[...] 항목 업데이트
  4. .env.example에서 일치하는 *_USER_AGENT 기본값 올리기
  5. TLS 핸드셰이크 자체가 변경된 경우 관련 공급자 래퍼 또는 wreq-js browser: 옵션 업데이트
  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은 계속 존재하는지 확인


OmniRoute 소스 코드 (a58000c7685f)

HagiCode

HagiCode는 구조화된 워크플로, 다중 에이전트 실행, Hero Dungeon 뷰를 갖춘 에이전트 코딩 작업 공간입니다.

더 스마트하고 빠르며 즐거운 에이전트 워크플로로 유용한 소프트웨어를 만드세요.

HagiCode 라이트 테마 메인 화면
  • Smart구조화된 워크플로는 의도를 아이디어부터 배포까지 실행 가능한 경로로 바꿉니다.
  • Efficient다중 에이전트 워크플로로 조사, 구현, 검토를 병렬로 진행합니다.
  • FunHero Dungeon은 긴 코딩 세션을 시각적이고 협업적인 경험으로 만듭니다.
HagiCode 방문