메뉴
HN
Hacker News 21일 전

포트리스(Fortress): 에이전트 차단을 우회하는 스텔스 크로미움

IMP
8/10
핵심 요약

포트리스(Fortress)는 크로미움(Chromium) C++ 엔진 내부에서 봇 탐지를 우회하도록 브라우저 지문(Fingerprint)을 수정하는 도구입니다. 기존 자바스크립트 우회 방식의 취약점을 해결하고, 코드 한 줄의 수정만으로 크라우드플레어(Cloudflare) 등 강력한 봇 탐지 시스템을 사람의 접속으로 인식시킬 수 있어 웹 자동화 및 스크래핑 실무자에게 매우 유용합니다.

번역된 본문

하나의 브라우저 엔진으로 모두를 제압하라 스텔스 크로미움 엔진 포트리스(Fortress)는 단 한 줄의 코드 변경만으로 스크래퍼와 브라우저 에이전트가 차단되는 것을 막아주는 스텔스 크로미움 엔진입니다. 봇 탐지기는 브라우저 지문(Fingerprint)을 읽어 자동화를 감지합니다. 포트리스는 크로미움의 C++ 내부에서 해당 지문을 교정하여, 브라우저가 일반적인 크롬 설치본처럼 보이게 만듭니다. 스크래퍼는 작업을 완료하고 에이전트는 이동해야 할 페이지에 도달하며, CreepJS, Sannysoft, BrowserScan 및 실제 작동 중인 Cloudflare Turnstile 역시 이를 사람으로 간주합니다.

기존에 사용하던 Playwright나 Puppeteer를 CDP를 통해 포트리스로 연결하기만 하면 코드의 다른 부분은 변경할 필요가 없습니다.

Blink · V8 · BoringSSL 트리 내 패치 · ANGLE / D3E11 기반 WebGL · JA3/JA4 일관성 있는 TLS · 월간 업스트림 리베이스 · 재현 가능한 철저한 검증을 거친 릴리스 34개의 단일 계층 C++ 패치 CreepJS 헤드리스 감지 0% / 모든 영역에서 스텔스 [native code] 유지 BSD-3 오픈 엔진, 직접 빌드 가능

실제 창에서 포트리스 바이너리의 편집되지 않은 캡처: 실제 Cloudflare 챌린지를 통과하고, bot.sannysoft.com을 모두 초록색으로 만들며, BrowserScan에서 "정상(Normal)"으로 판별합니다. tools/gauntlet.py로 재현해 볼 수 있습니다.

네이티브 코드 동일성 모든 스푸핑된 getter는 C++ getter입니다. toString은 [native code]를 반환하며, 메인 프레임, iframe 및 웹 워커(Web Workers) 전반에 걸쳐 영역(realm)이 변하지 않습니다.

드롭인 CDP Runtime.enable 누출이 없는 nodriver 방식의 원시 CDP를 :9222 포트에서 지원합니다. Playwright, Puppeteer 또는 기타 CDP 클라이언트를 그대로 사용하세요. 브라우저만 교체하고 코드는 유지할 수 있습니다.

모든 탐지 테스트 통과 CreepJS에서 헤드리스 감지 0%를 달성했습니다. Sannysoft, BrowserScan, 그리고 실제 Cloudflare Turnstile을 일반 크롬 설치본과 동일하게 모두 통과했습니다.

감사 가능한 패치 patches/ 폴더에 34개의 작고 단일 목적을 가진 diff 파일이 있습니다. 1분 안에 하나를 읽어볼 수 있으며, 단 하나의 스크립트로 엔진을 다시 빌드할 수 있습니다.

구조적인 일관성 실제 V8, Blink 및 BoringSSL을 사용하여 엔진, 사용자 에이전트(User-Agent), 그리고 JA3/JA4 TLS 형태가 일치합니다. 이는 일치하는 스택 위에서 구동되는 윈도우(Windows) 환경의 페르소나를 제공합니다.

조정 가능한 페르소나 하나의 바이너리로 일관성 검증이 된 윈도우 정체성을 제공합니다. --uxr-* 스위치를 통해 GPU, 화면, 시간대, 하드웨어, Client-Hints 등 모든 표면을 재정의할 수 있습니다.

🆕 새로운 소식 — 151.0.7908.0 · 엔진 새로 고침 릴리스 실행 시마다 일관성 있는 페르소나 제공, 보안 강화. 로케일별 키보드(QWERTY / QWERTZ / AZERTY), 페르소나별 미디어 기기 지원, 완전한 전달 일관성 패스를 포함하고 있습니다. 플랫폼 ↔ GPU ↔ 시간대 ↔ 언어 ↔ 음성 ↔ 키보드가 하나의 일관된 실제 기기처럼 움직입니다. 매 실행마다, 단일 바이너리에서 구현됩니다.

네이티브 코드 동일성(toString()이 [native code] 유지), 영역 불변성(메인 / 워커 / iframe 유지) — 자바스크립트에서 패치하는 것이 아니라 브라우저 자체에 일관성을 컴파일하여 내장했습니다.

pip install -U tilion-fortress

또는: docker run --rm -p 9222:9222 tilion/fortress:latest

→ 전체 릴리스 노트

목차 개요 · 빠른 시작: 소개, 설치, 첫 스크립트, AI 에이전트 설정 포트리스 MCP: AI 에이전트를 위한 29개의 스텔스 브라우저 도구(베타) 엔진을 패치하는 이유 (페이지가 아닌): 자바스크립트 기반 우회의 한계점 + 3가지 탐지 계층 비교: puppeteer-stealth, Camoufox, CloakBrowser 및 폐쇄형 벤더와의 비교 증명: 실시간 탐지기 결과 (CreepJS / Sannysoft / BrowserScan / Cloudflare 스크린샷) 페르소나 구성: --uxr-* 지문 표면 기존 스택과의 호환성: browser-use, Crawl4AI, Stagehand, LangChain 빌드 및 검증: 소스에서 재현, 출처 검증 참조: 문제 해결, FAQ, 로드맵, 저장소 구조

이것은 무엇인가 포트리스는 엔진 내부에서 브라우저 지문을 속이는 크로미움(Chromium) 포크입니다. 봇 탐지기가 읽는 표면(Canvas, WebGL, 오디오, 폰트, Navigator 등 약 30가지)을 크로미움의 C++에서 교정하여, 페이지가 발견할 수 있는 자바스크립트 패치 계층을 상단에 덧씌우지 않습니다. 이는 CDP 엔드포인트를 노출하는 일반적인 브라우저 바이너리로 제공됩니다. Playwright, Puppeteer 또는 기타 CDP 클라이언트를 이용해 연결하면 기존 자동화 코드를 수정하지 않고 그대로 실행할 수 있습니다.

자바스크립트 스텔스 패치는 페이지가 찾아낼 수 있는 추가 계층을 남깁니다. 예를 들어 .toString()은 재정의된 소스 코드를 보여주며, iframe이나 워커에서 동일한 원시 값을 다시 가져오면 이 우회 로직을 피해갑니다. 반면 포트리스는 엔진 자체에서 표면을 교정하기 때문에 navigator.vendor 등의 값이 정상적으로 해결됩니다.

원문 보기
원문 보기 (영어)
One browser engine to rule them all Stealth Chromium engine Fortress is a stealth Chromium engine that stops your scrapers and browser agents from getting blocked, with one line of code change. Bot detectors flag automation by reading the browser fingerprint; Fortress corrects that fingerprint inside Chromium's C++, so the browser presents as an ordinary Chrome install. Scrapers finish their runs, agents reach the pages they were sent to, and CreepJS, Sannysoft, BrowserScan, and live Cloudflare Turnstile all read it as human. Point your existing Playwright or Puppeteer at Fortress over CDP, and nothing else in your code changes. Blink · V8 · BoringSSL patched in-tree · ANGLE / D3D11 -backed WebGL · JA3/JA4-coherent TLS · monthly upstream rebase · reproducible, gauntlet-gated releases 34 single-surface C++ patches 0% CreepJS headless / stealth [native code] across every realm BSD-3 open engine, rebuild it yourself Unedited capture of the Fortress binary in a real window: it clears a live Cloudflare challenge, turns bot.sannysoft.com all green, then reads BrowserScan “Normal”. Reproduce with tools/gauntlet.py . Native-code parity Every spoofed getter is a C++ getter: toString returns [native code] , realm-invariant across main frame, iframes, and Web Workers. Drop-in CDP nodriver-style raw CDP on :9222 , with no Runtime.enable leak. Keep Playwright, Puppeteer, or any CDP client; swap the browser, keep your code. Clears the gauntlet 0% headless on CreepJS; Sannysoft, BrowserScan, and live Cloudflare Turnstile cleared, all as a stock Chrome install. Auditable patches 34 small single-purpose diffs in patches/ . Read one in a minute; rebuild the engine with one script. Coherent by construction Real V8, Blink, and BoringSSL keep engine, user-agent, and JA3/JA4 TLS shape in agreement: a Windows persona on a matching stack. Tunable persona One binary, a coherence-checked Windows identity; --uxr-* switches override any surface: GPU, screen, timezone, hardware, Client-Hints. 🆕 What's new — 151.0.7908.0 · Engine Refresh Released. Per-launch coherent personas, hardened. Per-locale keyboard (QWERTY / QWERTZ / AZERTY) · per-persona media devices · a full delivery-parity coherence pass. Platform ↔ GPU ↔ timezone ↔ language ↔ voices ↔ keyboard move as one coherent real device — on every launch, from a single binary. Native-code parity ( toString() stays [native code] ), realm-invariant (main / worker / iframe) — coherence compiled into the browser, not patched in JavaScript. pip install -U tilion-fortress # or: docker run --rm -p 9222:9222 tilion/fortress:latest → full release notes Contents What it is · Quick start what it is, install, first script, AI-agent setup The Fortress MCP 29 stealth-browser tools for AI agents (Beta) Why patch the engine, not the page the self-revealing-JS thesis + the three detection layers How Fortress compares vs puppeteer-stealth · Camoufox · CloakBrowser · closed vendors Proof: live-detector results CreepJS / Sannysoft / BrowserScan / Cloudflare, with screenshots Configure the persona the --uxr-* fingerprint surface Works with your stack browser-use · Crawl4AI · Stagehand · LangChain Build & verify reproduce from source, verify provenance Reference troubleshooting · FAQ · roadmap · repo layout What it is Fortress is a Chromium fork that spoofs the browser fingerprint from inside the engine. The surfaces bot detectors read (canvas, WebGL, audio, fonts, navigator, and about thirty more) are corrected in Chromium's C++ , with no JavaScript patch layer sitting on top for a page to catch. It ships as an ordinary browser binary that exposes a CDP endpoint. Point Playwright, Puppeteer, or any CDP client at it and your existing automation runs unchanged. A JavaScript stealth patch leaves an extra layer the page can find: .toString() shows the override's source, and re-grabbing the same primitive from an iframe or worker reaches past it. Fortress corrects the surface in the engine instead, so navigator.vendor resolves to the real C++ getter, reports [native code] , and reads the same from every realm. A page inspecting itself sees stock Chromium. That is why your automation gets through where it used to get flagged, and whatever blocking is left traces to your proxies and behavior rather than the browser. Why patch the engine, not the page covers the detection mechanics in full. from tilion_fortress import Fortress from playwright . sync_api import sync_playwright with Fortress () as f : # launches the stealth engine on a CDP endpoint with sync_playwright () as p : browser = p . chromium . connect_over_cdp ( f . cdp_url ) page = browser . new_page () page . goto ( "https://bot.sannysoft.com" ) page . screenshot ( path = "all-green.png" ) import { Fortress } from "tilion-fortress" ; import { chromium } from "playwright" ; const f = await Fortress . launch ( ) ; // stealth engine on a CDP endpoint const browser = await chromium . connectOverCDP ( f . cdpUrl ) ; const page = await browser . newPage ( ) ; await page . goto ( "https://browserscan.net" ) ; await browser . close ( ) ; await f . close ( ) ; The 12-second tour One loop, all real captures: passes CreepJS / Sannysoft / BrowserScan / rebrowser → scrapes structured data over CDP → clears Akamai on aa.com · lowes · macys · kohls (same residential IP). Real scraping, fully headless Unedited captures of the Fortress engine driven over CDP. No stealth plugins, no JS patches: the fingerprint is corrected in the binary. Reproduce any of these with examples/scrape_demos.py . Structured extraction : records build into typed JSON as each item is read. Auto-pagination : 30 quotes across 3 pages. Deep detail crawl : UPC · price · tax · stock · reviews. Clears real Akamai — before / after Same residential IP, same site ( aa.com · Akamai Bot Manager). A stock/headless browser gets Access Denied (Reference #); Fortress loads the real page and Akamai issues its _abck sensor cookie — the Bot Manager accepts it as a real browser. The variable is the fingerprint , not the IP. lowes.com · blocked → cleared macys.com · blocked → cleared kohls.com · blocked → cleared Not a one-site fluke — same before/after on major Akamai-protected retailers, every run from the same residential IP. Quick start # Python / Node: prebuilt native binary auto-fetched (Linux x64 & Windows x64), SHA-256 verified pip install tilion-fortress npm install tilion-fortress # Any OS via Docker: raw CDP on :9222 (~302 MB pull / 851 MB on disk, stripped single-layer) docker run --rm -p 9222:9222 tilion/fortress:latest # Portable bundle (extract-and-run, like a Chromium snapshot) tar xzf tilion-fortress-linux-x64.tar.gz # Linux ./tilion-fortress/tilion --headless=new --remote-debugging-port=9222 --user-data-dir=/tmp/p # Debian / Ubuntu sudo apt install ./tilion-fortress_151.0.7908.0_amd64.deb && tilion https://example.com Tip The SDK ships the compiled build plus patches/ , so you can rebuild the engine yourself and verify every surface correction against the source. Downloads are SHA-256-verified against the release SHA256SUMS automatically. Versions Fortress ships on two Chromium bases — pick your trade-off between blend-in and currency: Channel Chromium When to use stable (default) 149 Recommended — matches the Chrome version the mass of real users run, so it blends in best latest 151 Newest engine (reports a version slightly ahead of stable) Fortress (). start () # Python: stable (149) by default Fortress ( channel = "latest" ). start () # opt into 151 await Fortress . launch ( ) ; // Node: stable (149) by default await Fortress . launch ( { channel : "latest" } ) ; docker run --rm -p 9222:9222 tilion/fortress:149 # or :151 # or set FORTRESS_CHANNEL=latest for either SDK Native binaries: Linux x64 (both versions) + Windows x64 (151); Windows-149 and macOS run via the Docker image. Drop it into your AI agent Fortress is the browser your agent drives: raw CDP on :9222 , no stealth plugins to wire up. There are two ways in. Option 1: open