todo/mtproxy/tdlib-obf-client-side-stealth.md
loop-uh 0ad0bcc8dd
Some checks failed
Published content check / validate (push) Failing after 5s
seo+зеркало: [!mirror]-плашка со ссылкой на вики и description во frontmatter всех заметок
Каждая публикуемая заметка получила callout-шапку со ссылкой на свою страницу
wiki.zapret.moe (на самой вики она вырезается транформером RemoveMirrorCallout,
видна только на зеркале Obsidian Publish и в Forgejo) и SEO-поле description —
1–2 предложения для meta description обоих сайтов.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-26 22:05:57 +03:00

19 KiB
Raw Permalink Blame History

date tags aliases link description
2026-06-12
mtproto
mtproxy
dpi
tspu
ja4
faketls
tdlib
telegram
tdlib-obf
Клиентский TDLib с маскировкой JA4
Stealth TDLib
Обфусцированный TDLib
https://github.com/telemt/tdlib-obf tdlib-obf — форк TDLib с маскировкой MTProto под браузерный HTTPS: свежие JA4-профили Chrome/Firefox, ECH по маршруту и traffic shaping.

[!mirror] Резервное зеркало Актуальная версия этой страницы — на основной вики: wiki.zapret.moe/mtproxy/tdlib-obf-client-side-stealth

🦎 tdlib-obf — клиентский TDLib с маскировкой TLS-почерка под браузер

[!info] О чём заметка tdlib-obf — форк TDLib (официальной библиотеки для написания Telegram-клиентов) от сообщества telemt, который маскирует MTProto-трафик под обычный браузерный HTTPS, чтобы обходить государственный DPI (Deep Packet Inspection — глубокая инспекция пакетов; в РФ — оборудование ТСПУ, Технические Средства Противодействия Угрозам). Главное: это клиентская реализация — она меняет TLS-почерк (JA4) именно там, где это вообще возможно, внутри самого клиента. Тем самым tdlib-obf — это «полноценный» ответ на тезис из mtproxy/ja4-sni-client-side: чистый слом JA4 серверный прокси сделать не может, а форк клиента — может.

[!warning] Статус данных Технические детали ниже взяты в основном из собственного аудит-документа проекта (docs/Documentation/STEALTH_IMPLEMENTATION_RU.md, состояние на апрель–май 2026) — это самоотчёт авторов, не независимая проверка. Читай заявленные свойства маскировки как «по документации проекта», а не как подтверждённый внешним аудитом факт. Базовый коммит форка и ветка проверены напрямую по git (июнь 2026) и помечены отдельно.


TL;DR

  1. tdlib-obf — это TDLib с обфускацией: тот же API, но при сборке с флагом TDLIB_STEALTH_SHAPING=ON клиент строит TLS-рукопожатие, неотличимое (по замыслу) от реального браузера.
  2. Маскировка решает ровно тот рычаг, который mtproxy/ja4-sni-client-sideJA4-почерк ClientHello: вместо одного протухшего пресета Telegram используется реестр из 8 рантайм-профилей реальных браузеров (по аудит-доку — Chrome 120/131/133, Firefox 148/149, Safari, iOS, Android; в коде заведены и новые lanes), выбираемых на лету.
  3. Заодно адресуется беда Zapret/mtproto/10-telemt-logs-dpi: используемые Chrome-профили несут post-quantum key_share (ML-KEM), которого не было в старом почерке Telegram.
  4. Работает только через MTProto-прокси с FakeTLS (ProxySecret::emulate_tls()). Прямые соединения не маскируются (а часть leak-путей прямого TCP-SYN в обход прокси форк, по документации, дополнительно закрыл).
  5. Честное ограничение от самих авторов: после TLS идёт сырой MTProto, а не настоящий HTTP — полной неотличимости на уровне L7 проект не обещает.
  6. Это библиотека, а не готовый клиент: своё приложение пишешь поверх неё (проще всего — консольный клиент на libtdjson).

Термины (чтобы заметка читалась без контекста)

  • TDLib (Telegram Database Library) — официальная библиотека от Telegram для написания клиентов. Сама по себе не приложение, а движок: берёт на себя протокол, шифрование, базу сообщений. Готовые клиенты (Unigram, Telegram X) построены поверх неё.
  • libtdjson — собранная динамическая библиотека TDLib с JSON-интерфейсом, к которой подключаются из любого языка (Python, C++, и т.д.).
  • MTProto — собственный транспортный протокол Telegram (шифрование + формат пакетов), поверх которого работает мессенджер.
  • DPI / ТСПУ — DPI (Deep Packet Inspection) — глубокая инспекция пакетов; ТСПУ (Технические Средства Противодействия Угрозам) — это DPI-оборудование, установленное у российских операторов.
  • L7 — седьмой (прикладной) уровень модели OSI: грамматика самого протокола поверх TLS (HTTP/2, HTTP/1.1). «L7-неотличимость» — когда трафик неотличим от браузерного и на этом уровне, а не только в TLS-рукопожатии.
  • ClientHello / JA4 / SNI / FakeTLS — раскрыты в mtproxy/ja4-sni-client-side. Кратко: ClientHello — первый незашифрованный пакет TLS, который шлёт клиент; JA4 — его отпечаток; FakeTLS — режим MTProxy, где трафик маскируется под HTTPS.
  • ECH (Encrypted ClientHello) — расширение TLS, прячущее SNI внутри зашифрованной части рукопожатия.
  • DRS / IPT — внутренние подсистемы формирования трафика (traffic shaping): Dynamic Record Sizing (динамический размер TLS-записей) и Inter-Packet Timing (имитация тайминга пакетов).

Зачем это нужно: рычаг, который есть только у клиента

[!example] На пальцах Представь, что у входа стоит охранник (ТСПУ) и узнаёт «гостей Telegram» по визитке (JA4-почерк ClientHello). У официального клиента визитка одна и та же, к тому же устаревшего образца — охранник выучил её наизусть. Сервер-прокси переклеить визитку не может: гость показывает её до того, как дойдёт до сервера. А tdlib-obf — это сам гость, который печатает себе свежую визитку под видом обычного браузера перед каждым выходом.

Архитектурный факт, разобранный в mtproxy/ja4-sni-client-side: JA4 и SNI лежат в ClientHello, а его шлёт клиент, и цензор видит этот пакет ещё до сервера. Поэтому чистый слом почерка возможен только до цензора — на стороне клиента. До сих пор это воплощалось как отдельный локальный relay (тестовый gist Flowseal, который строит свой ClientHello). tdlib-obf идёт дальше: переносит ту же логику внутрь самого клиента-движка, без прослойки-relay.


Как работает маскировка (4 слоя)

По документации проекта, stealth-контур включает четыре одновременно работающих слоя:

Слой Что делает
Profile-driven ClientHello Реестр профилей реальных браузеров (по аудит-доку — Chrome 120/131/133, Firefox 148/149 вкл. macOS, Safari 26.3, iOS, Android; в коде есть и новые lanes — Chrome 147, Firefox 149 Windows/Android). Выбор «липкий» (sticky) — зависит от назначения, временного окна и платформы, чтобы не дёргать TLS-семейство на каждом соединении. Профили verified построены на реальных перехватах трафика, advisory — консервативные.
Route-aware ECH Политика ECH зависит от маршрута: на RU/неизвестных маршрутах ECH выключен, на не-RU — включается с «предохранителем» (circuit breaker), который отрубает ECH для направления после нескольких ошибок.
Transport shaping Имитация тайминга пакетов (IPT, не просто sleep(random), а burst/idle-модель), динамический размер TLS-записей (DRS: slow-start → congestion-open → steady-state), классификация типа трафика (handshake / keepalive / bulk / interactive).
Capture-driven верификация Сотни нативных тестов + «корпус» реальных перехватов, сверка отпечатков JA3/JA4 с эталонами, статистические прогоны на 1024 сидах — чтобы маскировка не «схлопывалась» в узнаваемый паттерн.

[!important] Это адресует «протухший почерк» #30733 Беда официального клиента из Zapret/mtproto/10-telemt-logs-dpi не в номере версии (он как раз представляется свежим Chrome 134/macOS), а в том, что его отпечаток идёт без post-quantum key_share, тогда как реальные Chrome 131+ его уже несут. К концу 2025 уже около половины «человеческих» TLS несут X25519MLKEM768 (по данным Cloudflare — ~43% к сентябрю и более 50% к декабрю 2025). По документации tdlib-obf синхронизирует PQ-группу между supported_groups и key_share в Chrome-профилях — то есть отпечаток выходит пост-квантовым, чего старому почерку Telegram не хватало.

[!note] Что закрывает, а что нет tdlib-obf бьёт по рычагу JA4/почеркего свежесть). Условие «один и тот же SNI в залпе» из mtproxy/ja4-sni-client-side — отдельная история: SNI в FakeTLS задаётся ee-секретом прокси (tls_domain), а не выводится из него, так что его ротация — вопрос того, к каким секретам/доменам подключается клиент, а не самого слоя маскировки. Третье условие — «залп на один ip:port» — частично снимается серверными мерами (pacing, разные порты), см. Zapret/mtproto/10-telemt-logs-dpi.


Как использовать

[!tip] Главное правило сборки Маскировка включается только при сборке с -DTDLIB_STEALTH_SHAPING=ON и только в режиме FakeTLS-прокси (ProxySecret::emulate_tls()). Жёсткий контракт: если использовать emulate_tls(), но собрать с TDLIB_STEALTH_SHAPING=OFF, процесс аварийно падает (LOG(FATAL)), а не работает молча без маскировки — «забыть включить» нельзя.

tdlib-obf — это библиотека, поэтому «свой клиент» = твоё приложение поверх её API. Практичный путь без написания C++:

  • Получить api_id/api_hash на my.telegram.org.
  • Собрать libtdjson из исходников с флагом TDLIB_STEALTH_SHAPING=ON (нужен компилятор C++23, OpenSSL, zlib ≥ 1.3.2, gperf, CMake — это единственная C++-часть).
  • Взять готовый терминальный клиент на TDLib (например tg от paul-nameless) и указать ему путь к своей libtdjson через library_path — получаешь рабочий клиент в терминале без своего кода.
  • Подключаться через MTProto-прокси с FakeTLS-секретом (ee…) — без него маскировки нет. Свой прокси можно поднять на mtproxy/mtproto-zig / telemt / mtg вне зоны блокировки.

[!warning] Готовый десктоп-GUI «в лоб» не подойдёт Telegram Desktop и его форки (Kotatogram, Materialgram) не используют TDLibу них свой MTProto-движок, подменить его на tdlib-obf нельзя. Из десктоп-GUI на TDLib есть Unigram (Windows), но его develop закреплён на более свежем коммите TDLib, чем база форка, и схема API (td_api.tl) за это время разошлась (на июнь 2026 — порядка 260 строк diff; точное число зависит от того, на какой коммит TDLib закреплён Unigram) — пересобрать Unigram с обфускацией можно только пересадив изменения форка на нужный коммит и разрулив конфликты. Поэтому самый дешёвый путь к рабочему клиенту — консольный/TUI на libtdjson.


Честные ограничения

Авторы прямо перечисляют их в документации — это плюс к прозрачности (но прозрачность не заменяет независимую проверку):

[!quote] Из документации проекта (раздел «Честные ограничения») После TLS-рукопожатия идёт сырой MTProto, а не браузероподобный HTTP. Полная L7-неотличимость не заявляется — на уровне глубокой L7-аналитики (настоящий HTTP/2-фрейминг, грамматика HTTP/1.1) трафик всё ещё может выделяться. Runtime-реестр профилей консервативнее эмпирического корпуса, а генерация ServerHello зависит от серверной стороны.

Дополнительно:

  • QUIC/HTTP3 запрещены — транспорт всегда TCP+TLS (allow_quic=true считается ошибкой конфигурации).
  • Это community-форк, не официальный Telegram (лицензия MIT поверх Boost-лицензии TDLib).

Версия и происхождение (проверено по git, июнь 2026)

  • Дефолтная ветка репозитория — master (не main).
  • Форк отделился от upstream TDLib на коммите 8fc2344f (25 апреля 2026). Сам форк схему td_api.tl тоже правит (+91/13 строк относительно базы) — это важно учитывать при попытке подружить его с готовым клиентом, заточенным под другую версию TDLib.
  • Мейнтейнеры — сообщество telemt (то же, что и Zapret/mtproto/00-overview).

📚 См. также

  • mtproxy/ja4-sni-client-side — архитектурный тезис, ответом на который и является tdlib-obf
  • mtproxy/tsrman-tg-android-faketls — родственный клиентский подход, но в виде готового приложения (форк Telegram-Android), а не библиотеки
  • Zapret/mtproto/10-telemt-logs-dpi — протухший JA4-почерк официального клиента, который tdlib-obf лечит PQ-профилями
  • mtproxy/mtproto-zig — серверная сторона FakeTLS-прокси, к которой подключается клиент
  • mtproxy/faketls-relay-diagnosis — как проверить снаружи, чей ClientHello релей не принимает, и какие требования он к нему предъявляет
  • Zapret/mtproto/00-overview — общий обзор экосистемы telemt
  • VLESS/dpi-tls-june-2026 — та же логика «И трёх условий» и про свежесть почерка/ML-KEM
  • 🔗 tdlib-obf на GitHub — исходники и документация (ветка master)
  • 🔗 tdesktop#30733 — протухший фингерпринт официального клиента