todo/DPI/curl-impersonate.md
loop-uh 08b4491545
Some checks failed
Published content check / validate (push) Failing after 3s
Завершить переезд базы знаний на Forgejo
Обновить правила репозитория и подписи исходников в 99 заметках, не затрагивая пользовательские незакоммиченные файлы. Сделать Forgejo Actions содержательным: проверять опубликованный commit, а не пустое рабочее дерево после checkout.
2026-08-07 08:27:28 +03:00

14 KiB
Raw Permalink Blame History

date tags aliases link
2026-07-16
dpi
tls
ja3
ja4
fingerprint
curl
tool
curl-impersonate
curl impersonate
Проверка блокировки по JA3/JA4
Имитация TLS-отпечатка браузера через curl
https://github.com/lwthiker/curl-impersonate

🥷 curl-impersonate — curl, притворяющийся браузером (проверка блокировок по TLS-отпечатку)

[!info] О чём заметка curl-impersonate — это специальная сборка curl, которая воспроизводит сетевой «почерк» настоящих браузеров: их TLS-рукопожатие (отпечатки JA3/JA4), параметры HTTP/2 и порядок заголовков. Заметка объясняет, что это за инструмент и как им проверять, блокирует ли DPI ваше соединение именно по отпечатку клиента, а не по адресу или содержимому. Теория самого механизма блокировки по отпечатку разобрана в DPI/browser-ja4-fingerprint-block и DPI/dpi-analysis-pipeline — здесь только инструмент.

[!warning] Статус проекта Последний релиз оригинального lwthiker/curl-impersonatev0.6.1 (март 2024), поэтому «свежие» профили в нём соответствуют браузерам того времени (вплоть до Chrome 116, Firefox 117). Отпечатки браузеров устаревают: реальный Chrome 2026 года даёт уже другой JA4, чем профиль chrome116. Для актуальных отпечатков смотрите активные форки/наследники проекта (например, экосистему curl_cffi в Python). Проверяйте, какой именно отпечаток отдаёт ваша сборка, прежде чем делать выводы.

TL;DR

  • Обычный curl имеет свой уникальный TLS-отпечаток, совсем не похожий на браузерный. Поэтому по «сигналу 2» (фингерпринт клиента) он и браузер выглядят для DPI по-разному.
  • curl-impersonate подделывает рукопожатие так, чтобы оно совпадало с конкретным браузером (Chrome, Edge, Firefox, Safari) — вплоть до набора TLS-расширений, шифронаборов, кривых и параметров HTTP/2.
  • Главная польза для темы обхода блокировок — диагностика: можно за секунды проверить, реагирует ли DPI на отпечаток клиента. Если сайт открывается через curl_ff117, но не через curl_chrome116 (или наоборот) — значит блокировка идёт по JA3/JA4, а не по IP или SNI.
  • Использование — через готовые wrapper-скрипты: curl_chrome116 https://example.com, curl_ff117 …, curl_safari15_3 ….
  • Есть и библиотека libcurl-impersonate.so — её можно подсунуть чужому приложению через LD_PRELOAD + CURL_IMPERSONATE=chrome116, не меняя код приложения.

Зачем это нужно: проблема отпечатка клиента

Многие серверы и системы фильтрации (в том числе DPI) отличают «настоящий браузер» от «скрипта/бота» не по паролю и не по IP, а по TLS-отпечатку — характеристике самого TLS-рукопожатия.

JA3 / JA4 — это стандартизированные способы свернуть параметры первого пакета TLS (ClientHello) в короткую строку-хеш: какие версии TLS предложены, в каком порядке идут шифронаборы, какие расширения включены, какие эллиптические кривые и т.д. У каждой программы этот набор свой и довольно стабильный, поэтому по нему можно опознать клиента, даже не расшифровывая трафик.

Проще говоря: ещё до того, как между вами и сайтом установится шифрование, ваша программа «представляется» — рассказывает, что она умеет и в каком порядке. Этот «акцент» у Chrome, Firefox и обычного curl разный, и наблюдатель посередине слышит разницу, не понимая ни слова из самого разговора.

Проблема в том, что обычные HTTP-клиенты (curl, requests, Go net/http) звучат совершенно не как браузер. Поэтому:

  • сервисы с анти-бот-защитой их блокируют, отдавая капчу или 403;
  • а DPI, наоборот, может блокировать именно браузерный отпечаток (как в [[DPI/browser-ja4-fingerprint-block|кейсе, где Chromium не открывал сайт, а curl открывал]]).

curl-impersonate решает обе стороны задачи: он позволяет curl-у звучать как выбранный браузер — а значит, воспроизвести ровно тот отпечаток, который вы хотите проверить.

Как реализована имитация

curl-impersonate добивается совпадения на трёх уровнях сразу — потому что подделать только заголовки недостаточно, отпечаток считается ниже, на уровне TLS.

  • TLS-уровень. Сборка под Chrome компилируется с BoringSSL (TLS-библиотека Google), под Firefox — с NSS (TLS-библиотека Mozilla). Это не косметика: сам стек TLS берётся «родной» для имитируемого браузера, плюс правятся расширения, шифронаборы и кривые, чтобы ClientHello совпал байт-в-байт с оригиналом.
  • HTTP/2-уровень. Подгоняются параметры HTTP/2-соединения (SETTINGS, WINDOW_UPDATE) и порядок псевдо-заголовков — по ним тоже строят отпечаток (см. DPI/tspu-h2-h3-fingerprint-hypothesis).
  • HTTP-заголовки. Wrapper-скрипты выставляют набор и порядок заголовков (User-Agent, Accept, sec-ch-* и т.д.) как у настоящего браузера.

Проще говоря: нельзя просто подменить User-Agent и стать Chrome — DPI и анти-бот-системы смотрят на то, как устроено само шифрованное рукопожатие, а не на то, что программа о себе пишет. curl-impersonate чинит именно рукопожатие, поэтому обмануть проверку получается.

Поддерживаемые браузеры (в оригинальной сборке v0.6.1)

Браузер Профили (версии)
Chrome 99, 100, 101, 104, 107, 110, 116 (Win10); 99 (Android 12)
Edge 99, 101 (Win10)
Firefox 91 ESR, 95, 98, 100, 102, 109, 117 (Win10)
Safari 15.3, 15.5 (macOS)

Полный актуальный список профилей лежит в файле browsers.json в репозитории. Имя профиля (например, chrome116) — это и есть аргумент для библиотеки и суффикс wrapper-скрипта.

Установка

Готовые бинарники для Linux и macOS (Intel) есть на странице релизов. Варианты:

  • Docker (быстро попробовать, ничего не ставя в систему):
docker pull lwthiker/curl-impersonate:0.6-chrome
docker run --rm lwthiker/curl-impersonate:0.6-chrome curl_chrome110 https://www.wikipedia.org
  • Arch Linux (AUR): yay -S curl-impersonate-bin
  • macOS (Homebrew, только Chrome): brew tap shakacode/brew затем brew install curl-impersonate
  • Зависимости для Firefox-сборки на Linux (нужен NSS):
sudo apt install libnss3 nss-plugin-pem ca-certificates

Использование

Через wrapper-скрипты (самый простой путь)

Для каждого профиля есть готовый скрипт-обёртка, который уже подставляет нужные TLS-опции и заголовки:

curl_chrome116 https://www.wikipedia.org
curl_ff117     https://www.wikipedia.org
curl_safari15_3 https://www.wikipedia.org

Дополнительные флаги передаются как обычному curl:

curl_chrome116 -H "Custom-Header: value" -v https://example.com

Как проверить блокировку по отпечатку (сценарий диагностики)

  • Открыть проблемный адрес обычным curl — записать результат (успех/RST/таймаут).
  • Повторить через curl_chrome116 (браузерный отпечаток Chromium).
  • Повторить через curl_ff117 (отпечаток Firefox) — у него другой JA4.
  • Сравнить: если один профиль проходит, а другой стабильно рвётся (TCP RetransmissionRST) при том же IP и SNI — блокировка идёт по отпечатку клиента, а не по адресу. Это ровно тот механизм, что описан в DPI/browser-ja4-fingerprint-block.

Через libcurl (для своих программ)

В комплекте есть libcurl-impersonate.so с дополнительной функцией:

CURLcode curl_easy_impersonate(struct Curl_easy *data,
                               const char *target,      // напр. "chrome116"
                               int default_headers);    // ставить ли браузерные заголовки

А чужое приложение, использующее libcurl, можно заставить имитировать браузер без правки его кода — через подмену библиотеки на Linux:

LD_PRELOAD=/path/to/libcurl-impersonate.so \
  CURL_IMPERSONATE=chrome116 \
  my_app

Переменная CURL_IMPERSONATE_HEADERS=no отключает автоматические браузерные заголовки, если вы хотите задать их вручную.

[!tip] Вердикт: это диагностический инструмент, а не средство обхода curl-impersonate удобен, чтобы подтвердить или опровергнуть гипотезу, что вас режут по JA3/JA4-отпечатку. Для повседневного обхода DPI он не нужен — там применяют другие подходы (uTLS/REALITY-фингерпринт в VLESS, десинхронизацию в Zapret). Но как «пробник» для воспроизведения конкретного отпечатка он незаменим: даёт быстрый, скриптуемый способ послать в сеть именно тот ClientHello, который вы хотите протестировать.

📚 См. также

  • DPI/browser-ja4-fingerprint-block — зачем вообще воспроизводить отпечаток: реальный случай, где Chromium резался, а curl проходил
  • DPI/dpi-analysis-pipeline — где в цепочке фильтрации стоит проверка отпечатка клиента
  • DPI/tspu-h2-h3-fingerprint-hypothesis — второй уровень, который тоже имитирует curl-impersonate
  • 🔗 curl-impersonate на GitHub — исходники, релизы, browsers.json
  • 🔗 Страница релизов — готовые бинарники и Docker-образы

[!quote] 🤖 Эти статьи открыты — можно обучать на них ИИ При желании вы можете натренировать ИИ на наших статьях. Исходное форматирование и скачивание всего репозитория одним zip-архивом доступны в Forgejo: исходник этой заметки · весь репозиторий.