
HTTP-прокси следующего поколения для скрытной работы, который идеально маскирует запросы под браузер Chrome на всех уровнях стека.
«Не могу поверить, термооптический камуфляж!»
Это HTTP-прокси, предназначенный для обхода сервисов, которые используют такие методы снятия отпечатков, как JA4+, для блокировки определённых HTTP-клиентов. С помощью этого прокси вы можете использовать привычные HTTP-клиенты, например curl, и при этом получать волшебным образом неотличимые от настоящего (Chrome/Chromium) веб-браузера отпечатки. thermoptic также включает несколько интересных функций для смягчения JavaScript-отпечатков. Кроме того, он упрощает гибридный скрапинг, позволяя использовать веб-браузер и низкоуровневые HTTP-клиенты вместе.
Даже если вы не знакомы с отпечатками JA4+, то, если вы когда-либо занимались скрапингом, вас, скорее всего, уже блокировали с их помощью. Популярные сервисы, такие как Cloudflare, используют подобные методы (и другие уловки), чтобы обнаруживать «нечеловеческих» HTTP-клиентов и блокировать их запросы. Эти сервисы также могут использовать это снятие отпечатков, чтобы определить, начали ли вы сессию в настоящем браузере, а затем переключились на низкоуровневый клиент вроде curl. thermoptic решает все эти проблемы, предоставляя единый «настоящий» отпечаток браузера для всех запросов скрапинга.
Вот пример отпечатка JA4H (HTTP) для curl без прокси:```
$ curl https://ja4db.com/id/ja4h/
ge11nn090000_b6a016211e8a_000000000000_e3b0c44298fc
Это сильно отличается от отпечатка, который Chrome создаёт при прямом посещении URL:```
ge11cn19enus_f2808f0d04cf_9a10d4221160_7068f58def6e
Однако, когда мы используем прокси для выполнения запроса, наш JA4H-отпечаток магическим образом становится идентичным:``` $ curl --proxy http://thermoptic:1234 https://ja4db.com/id/ja4h/ ge11cn19enus_f2808f0d04cf_9a10d4221160_7068f58def6e
(То же самое касается и нашего JA4 TLS-отпечатка, и т. д.).
## Настройка
Чтобы запустить прокси `thermoptic`, который маскирует ваш трафик через контейнеризованный экземпляр Chrome на Ubuntu 22.04:
Обычная настройка Docker (работает на хостах без GPU-рантайма):```
docker compose up --build
Вот и всё, теперь вы можете проксировать трафик через него:``` curl --proxy http://127.0.0.1:1234 --insecure https://ja4db.com/id/ja4h/
Важные замечания:
* По умолчанию прокси работает без аутентификации. Если вы планируете открыть доступ к прокси извне, обязательно настройте аутентификацию с помощью переменных окружения `PROXY_USERNAME` и `PROXY_PASSWORD`.
* Если вы не хотите использовать `---insecure`, вам нужно использовать сгенерированный файл CA, расположенный в `./ssl/rootCA.crt`. Он создаётся при первом запуске `thermoptic`.
* Вы можете подключить `thermoptic` к любому экземпляру Chrome/Chromium, запущенному с флагом `--remote-debugging-port`. Это важно, так как вам захочется настроить и использовать прокси через более привычные окружения, чтобы ваш отпечаток был как можно более незаметным (например, Chrome в Windows).
* Переопределение GPU в compose предназначено для хостов NVIDIA, на которых уже установлены Docker-рантайм/тулкит NVIDIA. Оно резервирует GPU-устройство, монтирует `/dev/dri` и позволяет встроенному контейнеру Chrome переключиться на путь рендеринга NVIDIA/Vulkan. Чтобы использовать это, выполните `docker compose -f docker-compose.yml -f docker-compose.gpu.yml up --build`.
## Возможности
- 🕵️ [Проксирование с паритетом браузера](#how-does-this-cloaking-work-exactly), которое воспроизводит запросы через реальную сессию Chrome, чтобы соответствовать отпечаткам JA4 байт в байт.
- 🤝 Для интеграции вашего HTTP-клиента (например, `curl`, `requests` и т.д.) с `thermoptic` требуется мало или вообще не требуется пользовательского кода — просто [настройте прокси](#setup), и ваши отпечатки будут обработаны.
- 🪝 [Каркас хуков](#handling-browser-javascript-fingerprinting-with-thermoptic-hooks) для автоматизации before-request/after-request/on-start, позволяющий управлять полным браузером для решения задач или сбора артефактов.
- 📘 Пример хука для решения Cloudflare turnstile можно увидеть в [`./hooks/onstart.js`](https://github.com/mandatoryprogrammer/thermoptic/blob/main/hooks/onstart.js).
- 🖥️ [Веб-интерфейс управления браузером](#control-the-dockerized-chrome-browser-via-web-ui-xpra) (по адресу `http://127.0.0.1:14111`) для управления окном браузера Chrome в Docker. Полезен для ручного входа на сайты, после чего можно seamlessly использовать прокси для выполнения запросов от имени вашей авторизованной сессии (а также для отладки).
- 🔌 Задайте URI вышестоящего HTTP- или SOCKS-прокси через переменную окружения `UPSTREAM_PROXY` в `docker-compose.yml`.
- 🛡️ Встроенные проверки работоспособности и контур управления перезапуском для обнаружения зависших браузеров и автоматического восстановления без постоянного участия оператора.
- ⚡ Поддержка HTTP/1.1 и HTTP/2, что позволяет проксировать трафик по любому из этих протоколов. (_Обратите внимание: вы можете общаться с прокси по HTTP/1.1, а управляемый Chrome может согласовывать с конечным сайтом другой протокол._)
## Как именно работает эта маскировка?

* HTTP-запрос выполняется с помощью HTTP-клиента, такого как `curl`, с `thermoptic` в качестве прокси.
* `thermoptic` анализирует запрос, чтобы наилучшим образом определить, каким браузерным запросом он *должен* быть (например, ручное посещение URL? Отправка формы? Запрос `fetch()`?).
* `thermoptic` использует [Chrome Debugging Protocol (CDP)](https://chromedevtools.github.io/devtools-protocol/) для управления браузером и настройки страницы, которая имитирует запрос точно так, как он обычно происходит в реальном веб-браузере.
* `thermoptic` запускает запрос через имитированный контекст и перехватывает HTTP-ответ.
* `thermoptic` отправляет HTTP-ответ обратно клиенту.
Благодаря тому, что запрос фактически выполняется браузером с использованием всего его стека, результирующие отпечатки JA4 идентичны.
ПРИМЕЧАНИЕ. Поскольку многие WAF используют JavaScript-фingerprinting на уровне браузера, `thermoptic` также предоставляет хуки для использования браузера на ключевых этапах процесса scraping. Дополнительную информацию см. в [этом разделе](#handling-browser-javascript-fingerprinting-with-thermoptic-hooks).
## Почему именно *такой* подход, а не другие решения?
Если говорить прямо: другие подходы имеют фундаментальные недостатки, которые мешают им быть практичным долгосрочным решением проблемы браузерного фингерпринтинга.
Многие другие попытки «обойти» JA4+ фингерпринтинг браузера делают это путём повторной реализации различных уровней стека браузера. У такого подхода есть ряд серьёзных недостатков, например:
* Требуется большая осторожность, чтобы идеально соответствовать поведению «настоящей» реализации браузера. В результате *любые* особенности или расхождения могут быть использованы для отличия таких клиентов от «настоящей» реализации браузера.
* Попытка решить проблему только на одном уровне стека. Chrome использует несколько протоколов для обеспечения работы в веб-браузере. В результате, даже если вы создали идеально совпадающий TLS-уровень, ваш HTTP-уровень может вас выдать, если он не совпадает байт в байт.
* Поскольку «настоящие» браузеры регулярно меняют своё поведение, их отпечатки меняются, и в результате эти инструменты постоянно требуют более интенсивной разработки для компенсации.
В отличие от этого, поскольку `thermoptic` использует сам браузер для выполнения HTTP-запросов:
* Каждый уровень стека, такой как TCP, TLS, HTTP, неотличим от реального браузера, потому что запрос выполняется *с помощью* реального браузера так, как он это делает *обычно*.
* Изменения в поведении браузера на различных уровнях минимально разрушительны — браузер, которым управляет `thermoptic`, нужно просто обновить, чтобы соответствовать последнему набору отпечатков.
Конечно, ни одно решение не лишено недостатков. См. документацию `DOWNSIDES.md` для полного списка недостатков подхода `thermoptic`.
## FAQ
### Почему такое название — `thermoptic`?
«Thermoptic» (сокращение от «thermoptic camouflage») — это отсылка к вымышленному камуфляжу, [используемому Майором в аниме «Призрак в доспехах» (1995)](https://ghostintheshell.fandom.com/wiki/Thermoptic_camouflage). В фильме этот камуфляж способен скрывать носителя от множества спектров обнаружения, включая как видимый свет, так и тепловое излучение. Аналогично, этот инструмент пытается скрыть пользователя от фингерпринтинга по нескольким каналам (HTTP, TLS и т.д.).
### JA4+ — это **набор** отпечатков! Какие из них он подделывает?
Этот инструмент будет подделывать следующие отпечатки JA4, чтобы они точно соответствовали браузеру Chrome/Chromium, к которому вы подключены:
* JA4 (TLS-отпечаток)
* JA4H (HTTP-отпечаток)
* JA4X (X509 TLS-отпечаток сертификата)
* JA4T (TCP-отпечаток)
### Что если я хочу использовать другой вышестоящий HTTP/SOCKS прокси вместе с этим?
`thermoptic` теперь маршрутизирует управляемый экземпляр Chrome через внутренний сервис `proxyrouter`, поэтому вы можете направить Chrome на вышестоящие HTTP- или SOCKS-прокси (включая те, которые требуют учётные данные). Задайте URI вышестоящего прокси, изменив значение `UPSTREAM_PROXY` в `docker-compose.yml` в сервисе `proxyrouter`. Если оставить его пустым, Chrome будет общаться с интернетом напрямую через неаутентифицированный прокси внутри кластера.
Пример настройки вышестоящего SOCKS-прокси:```yaml
proxyrouter:
environment:
UPSTREAM_PROXY: "socks5://username:[email protected]:1080"
Имейте в виду, что некоторые вышестоящие прокси могут изменять низкоуровневые отпечатки (например, TCP-метаданные), что может снизить степень соответствия обычному домашнему браузеру.
thermoptic загрузит браузер с теми cookies, которые ваш клиент указывает в заголовке Cookie. Затем запрос включит их, когда выполнится в контексте браузера. Это сделано для того, чтобы сервер не мог снять отпечаток с порядка cookies или использовать любые другие подобные дешёвые трюки.
ПРИМЕЧАНИЕ: эти cookies также сохранятся после выполнения запроса. Если вы хотите реализовать логику очистки cookies, пожалуйста, напишите хук thermoptic.
Да, thermoptic поддерживает гибридное использование в таких случаях, см. этот раздел для получения дополнительной информации.
Вам нужно убедиться, что вы правильно задаёте такие заголовки, как X-Fetch-*, Origin и Referer. Если вы не сообщите thermoptic об этих заголовках, он не сможет выполнить запрос достаточно скрытным образом.
Без задания контекстных заголовков thermoptic установит значения по умолчанию, которые могут не полностью соответствовать ожиданиям вашего целевого сайта. Например, если вы не зададите заголовок Origin, он установит Origin равным null; если вы не зададите заголовок Referer, он просто вообще не отправит Referer.
В ваших интересах включать эти контекстные заголовки, чтобы ваш запрос был как можно более скрытным! thermoptic не умеет читать ваши мысли, он может читать только ваш запрос :).
Как правило, это относится только к случаям хуков thermoptic, которые временно используют полноценный веб-браузер для прохождения проверок на уровне JavaScript/браузера. При временном использовании таких хуков и режима полного браузера нужно быть осторожным, чтобы вас не распознали как бота (например, избегать ловушек вроде Runtime.enable).
Этические соображения и сложная теория игр, действующие здесь, выходят далеко за рамки того, что можно описать в README. Впрочем, не стесняйтесь оспаривать любой из этих упрощённых пунктов, когда будете поливать меня грязью по email/Twitter/GitHub:
Для дальнейших обсуждений гонки вооружений в сфере скрапинга прошу как минимум сначала угостить меня пивом. Честно говоря, я ненавижу писать эти скучные этические эссе в своих README, так что можете просто представить меня злым гиком, который хочет сделать вашу жизнь сложнее.
thermopticthermoptic позволяет настраивать собственные скрипты для выполнения действий в браузере, когда:
ON_START_HOOK_FILE_PATH)BEFORE_REQUEST_HOOK_FILE_PATH)AFTER_REQUEST_HOOK_FILE_PATH)Это позволяет вам использовать Chrome Debugging Protocol для кликов и установки соответствующих cookies на сайтах, требующих реальный веб-браузер для этапа верификации. Затем вы можете использовать прокси thermoptic, чтобы продолжить свою сессию незаметно через тот же браузер.
Для этого измените соответствующий файл хука на JavaScript, добавив свой код, чтобы управлять браузером соответствующим образом через предоставляемый интерфейс chrome-remote-interface:```
// cdp is an instance of a connected browser, use it to run your browser actions
export async function hook(cdp) {
console.log([STATUS] Browser start hook called successfully!);
}
Для примера реализации см. файл [`./hooks/onstart.js`](https://github.com/mandatoryprogrammer/thermoptic/blob/main/hooks/onstart.js), который [обходит Cloudflare turnstile CAPTCHA](https://github.com/mandatoryprogrammer/thermoptic/blob/main/tutorials/turnstile/cloudflare-turnstile-bypass.md) (а также другие антибот-проверки Cloudflare).
## Управление браузером Chrome в Docker через веб-интерфейс (Xpra)
`thermoptic` поставляется с веб-интерфейсом Xpra, доступным по адресу `http://127.0.0.1:14111`. Это позволяет легко управлять браузером Chrome в Docker вручную:
<img src="https://assets.kitploit.com/production/public/readmes/49068/0fa1b187f46405dda2b0db5d461619daa6a7bdad2c385cb51994e870d9054d10.png" width="100%">
Это полезно для таких задач, как:
* Вход в ваш аккаунт, чтобы вы могли отправлять аутентифицированные запросы через `thermoptic` с помощью предпочитаемого HTTP-клиента, например `curl`.
* Например, если вы войдёте в `reddit.com` через браузер, то все запросы к Reddit, которые вы отправляете через `thermoptic`, будут автоматически аутентифицированы от имени вашего аккаунта Reddit!
* Отладка ваших собственных хуков `thermoptic` и проверка проблем с веб-сайтами.
## Конфигурация
Следующие переменные окружения определяют, как `thermoptic` должен быть настроен при запуске.
`HTTP_PROXY_PORT`: порт, на котором должен прослушиваться прокси-сервер `thermoptic`. Если вы запускаете `thermoptic` в Docker, вам также нужно изменить поле сопоставления `ports` соответствующим образом.
`CHROME_DEBUGGING_PORT`: порт, на котором доступен Chrome Debugging Protocol. Этот порт задаётся при запуске Chrome/Chromium с флагом `--remote-debugging-port`, установленным в значение например `9222`.
`CHROME_DEBUGGING_HOST`: хост, на котором доступен Chrome Debugging Protocol. Обычно это `127.0.0.1`, если браузер запущен локально и `thermoptic` не работает в Docker. Если он работает в Docker, возможно, придётся использовать `host.docker.internal`; см. [документацию Docker](https://docs.docker.com/desktop/features/networking/#i-want-to-connect-from-a-container-to-a-service-on-the-host) для получения информации.
`PORT`: порт CDP, который контейнер Chrome публикует для остальной части стека. Держите его согласованным с `CHROME_DEBUGGING_PORT`, чтобы мост `socat` продолжал работать как ожидается.
`CHROME_CONTROL_PORT`: порт службы управления Chrome, который thermoptic использует для управления браузером (например, для отправки запросов на перезапуск).
`CHROME_CONTROL_COOLDOWN_MS`: минимальное время в миллисекундах между попытками перезапуска Chrome. Используйте это, чтобы избежать быстрых циклов перезапуска, когда несколько сбоев происходят подряд.
`ENABLE_GUI_CONTROL`: установите значение `true`, чтобы запустить веб-панель xpra и управлять Chrome в контейнере, посетив `http://127.0.0.1:14111`. Отключите для запусков только в headless-режиме.
`CHROME_SCREEN_WIDTH` / `CHROME_SCREEN_HEIGHT`: размеры в пикселях дисплея Chrome с графическим интерфейсом в Docker.
`CHROME_ENABLE_GPU`: управляет тем, должен ли встроенный контейнер Chrome пытаться использовать аппаратное ускорение GPU хоста. `auto` (по умолчанию) включает путь NVIDIA/Vulkan, когда присутствуют необходимые runtime и узлы устройств, в противном случае выполняется откат к программному рендерингу. Установите значение `false`, чтобы принудительно использовать прежнее поведение только с программным рендерингом.
`CHROME_PROFILE_RECOVERY`: если установлено `true` (по умолчанию), встроенный лаунчер Chrome выполнит одну попытку восстановления, если Chrome немедленно завершится с тем же кодом выхода при зацикливании сбоя, который наблюдается в повреждённом профиле (`133`). Содержимое повреждённого профиля перемещается в `/tmp/chrome-profile-recovery/` внутри контейнера перед повторной попыткой с чистым профилем.
`PROXY_USERNAME`: имя пользователя, которое используется для вашей аутентификации на прокси-сервере, по умолчанию `changeme`. Если не задано, прокси работает без требования аутентификации.
`PROXY_PASSWORD`: пароль, который используется для вашей аутентификации на прокси-сервере, по умолчанию `changeme`. Если не задан, прокси работает без требования аутентификации.
`THERMOPTIC_CONTAINER_RUNTIME`: указывает, что thermoptic работает внутри встроенного контейнера. Оставьте значение `true`; оно включает такие функции, как встроенные проверки работоспособности, которые имеют смысл только в полной Docker-установке.
`HEALTHCHECK_ENDPOINT_PORT`: порт, на котором thermoptic предоставляет свою веб-точку проверки работоспособности. Рабочий процесс проверки вызывает её через прокси; если она перестаёт отвечать, Chrome автоматически перезапускается, чтобы разблокировать зависшие сессии.
`HEALTHCHECK_ENDPOINT_PATH`: HTTP-путь, обслуживаемый описанной выше точкой проверки работоспособности. Измените его, если вам нужен другой URL.
`ON_START_HOOK_FILE_PATH`: пользовательский код Node для выполнения при запуске прокси. Прокси не начнёт прослушивание, пока этот хук не завершится; см. пример в `./hooks/`. Пример демонстрирует использование браузера для прохождения JavaScript-проверки браузера Cloudflare перед запуском прокси.
`BEFORE_REQUEST_HOOK_FILE_PATH`: пользовательский код Node для выполнения перед проксированием запроса. Это полезно, если нужно, чтобы браузер прошёл какую-либо проверку перед выполнением HTTP-запроса к сайту.
`AFTER_REQUEST_HOOK_FILE_PATH`: пользовательский код Node для выполнения после проксирования запроса. Это часто полезно для таких действий, как очистка cookie-файлов, установленных клиентом через заголовок `Cookie`.
`DEBUG`: установите значение `true`, если вы столкнулись с ошибкой, чтобы thermoptic выводил подробную диагностику перед тем, как вы создадите issue; оставьте `false` при обычной работе.
## Безопасность
Обратите внимание, что в настоящее время `thermoptic` предназначен для использования только с HTTP-клиентами, которым вы явно доверяете. Он *не* предназначен для предоставления доступа ненадёжным пользователям.
О любых уязвимостях безопасности, пожалуйста, отправляйте отчёт мне на `mandatory@` Gmail.