Каждая публикуемая заметка получила callout-шапку со ссылкой на свою страницу wiki.zapret.moe (на самой вики она вырезается транформером RemoveMirrorCallout, видна только на зеркале Obsidian Publish и в Forgejo) и SEO-поле description — 1–2 предложения для meta description обоих сайтов. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
19 KiB
| date | tags | aliases | link | description | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2026-06-12 |
|
|
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
tdlib-obf— это TDLib с обфускацией: тот же API, но при сборке с флагомTDLIB_STEALTH_SHAPING=ONклиент строит TLS-рукопожатие, неотличимое (по замыслу) от реального браузера.- Маскировка решает ровно тот рычаг, который mtproxy/ja4-sni-client-side — JA4-почерк ClientHello: вместо одного протухшего пресета Telegram используется реестр из 8 рантайм-профилей реальных браузеров (по аудит-доку — Chrome 120/131/133, Firefox 148/149, Safari, iOS, Android; в коде заведены и новые lanes), выбираемых на лету.
- Заодно адресуется беда Zapret/mtproto/10-telemt-logs-dpi: используемые Chrome-профили несут post-quantum
key_share(ML-KEM), которого не было в старом почерке Telegram. - Работает только через MTProto-прокси с FakeTLS (
ProxySecret::emulate_tls()). Прямые соединения не маскируются (а часть leak-путей прямого TCP-SYN в обход прокси форк, по документации, дополнительно закрыл). - Честное ограничение от самих авторов: после TLS идёт сырой MTProto, а не настоящий HTTP — полной неотличимости на уровне L7 проект не обещает.
- Это библиотека, а не готовый клиент: своё приложение пишешь поверх неё (проще всего — консольный клиент на
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 — протухший фингерпринт официального клиента