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

149 lines
14 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
date: 2026-07-16
tags:
- dpi
- tls
- ja3
- ja4
- fingerprint
- curl
- tool
aliases:
- curl-impersonate
- curl impersonate
- Проверка блокировки по JA3/JA4
- Имитация TLS-отпечатка браузера через curl
link: 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|кейсе с JA4-блокировкой]] и [[DPI/dpi-analysis-pipeline|воронке проверок DPI]] — здесь только инструмент.
> [!warning] Статус проекта
> Последний релиз оригинального `lwthiker/curl-impersonate` — **v0.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/2 и HTTP/3]]).
- **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) есть на [странице релизов](https://github.com/lwthiker/curl-impersonate/releases). Варианты:
- **Docker** (быстро попробовать, ничего не ставя в систему):
```bash
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):
```bash
sudo apt install libnss3 nss-plugin-pem ca-certificates
```
## Использование
### Через wrapper-скрипты (самый простой путь)
Для каждого профиля есть готовый скрипт-обёртка, который уже подставляет нужные TLS-опции и заголовки:
```bash
curl_chrome116 https://www.wikipedia.org
curl_ff117 https://www.wikipedia.org
curl_safari15_3 https://www.wikipedia.org
```
Дополнительные флаги передаются как обычному `curl`:
```bash
curl_chrome116 -H "Custom-Header: value" -v https://example.com
```
### Как проверить блокировку по отпечатку (сценарий диагностики)
- [ ] Открыть проблемный адрес обычным `curl` — записать результат (успех/`RST`/таймаут).
- [ ] Повторить через `curl_chrome116` (браузерный отпечаток Chromium).
- [ ] Повторить через `curl_ff117` (отпечаток Firefox) — у него **другой** JA4.
- [ ] Сравнить: если один профиль проходит, а другой стабильно рвётся (`TCP Retransmission``RST`) при том же IP и SNI — блокировка идёт **по отпечатку клиента**, а не по адресу. Это ровно тот механизм, что описан в [[DPI/browser-ja4-fingerprint-block|кейсе JA4-блокировки]].
### Через libcurl (для своих программ)
В комплекте есть `libcurl-impersonate.so` с дополнительной функцией:
```c
CURLcode curl_easy_impersonate(struct Curl_easy *data,
const char *target, // напр. "chrome116"
int default_headers); // ставить ли браузерные заголовки
```
А чужое приложение, использующее libcurl, можно заставить имитировать браузер **без правки его кода** — через подмену библиотеки на Linux:
```bash
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|Блокировка по JA4-отпечатку браузера (кейс wireflow.space)]] — зачем вообще воспроизводить отпечаток: реальный случай, где Chromium резался, а `curl` проходил
- [[DPI/dpi-analysis-pipeline|Как DPI анализирует соединение: воронка проверок]] — где в цепочке фильтрации стоит проверка отпечатка клиента
- [[DPI/tspu-h2-h3-fingerprint-hypothesis|Гипотеза об отпечатке HTTP/2 и HTTP/3]] — второй уровень, который тоже имитирует curl-impersonate
- 🔗 [curl-impersonate на GitHub](https://github.com/lwthiker/curl-impersonate) — исходники, релизы, `browsers.json`
- 🔗 [Страница релизов](https://github.com/lwthiker/curl-impersonate/releases) — готовые бинарники и Docker-образы
---
> [!quote] 🤖 Эти статьи открыты — можно обучать на них ИИ
> При желании вы можете натренировать ИИ на наших статьях. Исходное форматирование и скачивание всего репозитория одним zip-архивом доступны в Forgejo: [исходник этой заметки](https://git.zapret.moe/zapretdiscordyoutube/todo/src/branch/main/DPI/curl-impersonate.md) · [весь репозиторий](https://git.zapret.moe/zapretdiscordyoutube/todo/src/branch/main).