# TLS Fingerprint — DPI Detection Technique ## Источник Статья на Хабре: [Конец удобства? Почему MTProxy начал ломаться](https://habr.com/ru/articles/1018672/) (2 апреля 2026, s4q) ## Суть техники DPI (Deep Packet Inspection) анализирует TLS ClientHello на предмет узнаваемого отпечатка (fingerprint). Отпечаток складывается из: - Порядка cipher suites - Списка TLS extensions - Supported groups (elliptic curves) - Signature algorithms - Версии TLS - Других параметров ClientHello У каждого TLS-клиента (браузер, Telegram, curl) — уникальная комбинация этих параметров. DPI сравнивает её с базой известных fingerprint'ов и принимает решение: пропустить, деградировать (RST-инъекция) или дропнуть пакеты. ## Применимость к XRay Reality XRay Reality принципиально отличается от MTProxy/Fake-TLS тем, что **не имитирует TLS, а использует настоящий TLS-сервер** (reddit.com, cloudflare.com и т.д.) как маскировку. Reality: 1. Принимает ClientHello от клиента 2. Проверяет REALITY-подпись (publicKey + shortId + время) 3. Если подпись невалидна — проксирует соединение на реальный сервер (dest), как обычный HTTPS 4. Если подпись валидна — расшифровывает VLESS-трафик **Разница с MTProxy:** MTProxy использует Fake-TLS — сам отправляет поддельный ServerHello, не обращаясь к реальному серверу. У Reality — настоящий TLS-сервер на backend'е, поэтому поведение трафика после рукопожатия неотличимо от браузерного. ## Почему это важно для диагностики Когда в логах XRay появляется `REALITY: failed to read client hello`, это может быть следствием: 1. **Неверный publicKey/shortId в клиенте** — DPI не при чём, чисто конфигурационная проблема 2. **DPI обрезает ClientHello на уровне сети** — пакет приходит повреждённым/обрезанным 3. **Клиент отправляет ClientHello с нестандартными параметрами** — например, из-за ошибки в реализации TLS ### Случай из статьи: баг в encrypted_client_hello Telegram В коде генерации `encrypted_client_hello` у Telegram нашли ошибку: - Формируется нестандартное TLS-расширение с **неверным ID** и **некорректной длиной** - Из-за этого ClientHello Telegram легко матчится ТСПУ - Патч подготовлен, но на момент статьи не смерджен в официальный tdesktop **Этот случай — иллюстрация того, как даже небольшая ошибка в TLS-реализации клиента делает его узнаваемым для DPI.** Применительно к XRay: если клиент (v2rayNG, XRay-core на Android) отправляет ClientHello, который отличается от нормального браузерного, DPI может отфильтровать соединение ещё до того, как XRay сервер успеет проверить REALITY-подпись. ## Как DPI взаимодействует с XRay Reality ### Вариант A — Дроп после ClientHello ```mermaid sequenceDiagram Client->>DPI: TCP SYN DPI->>Server: TCP SYN Server->>DPI: TCP SYN-ACK DPI->>Client: TCP SYN-ACK Client->>DPI: TCP ACK Client->>DPI: TLS ClientHello DPI->>DPI: Анализ fingerprint Note over DPI: ClientHello не похож на браузерный?
Дропаем/инжектим RST DPI->>Client: RST (поддельный) ``` **Проявление:** `failed to read client hello` в логах сервера, при этом TCP SYN успешно доходит. ### Вариант B — Деградация после установки соединения DPI пропускает ClientHello, но после установки REALITY-сессии анализирует поведение трафика. Если трафик не похож на HTTPS — начинает дропать пакеты. **Проявление:** соединение устанавливается, работает несколько секунд/минут, потом обрывается. ### Дополнительные механизмы DPI из статьи Статья описывает несколько техник DPI, которые выходят за рамки простого fingerprint-матчинга: 1. **Поведенческий анализ после соединения:** DPI может пропустить ClientHello, установить TLS-сессию, но затем анализировать **паттерны трафика** (размеры пакетов, частоту, направление). Если трафик не похож на HTTPS-сёрфинг (например, идёт постоянный поток данных без видимых HTTP-запросов), DPI начинает дропать или деградировать соединение. 2. **Деградация (throttling) вместо блокировки:** Вместо RST или дропа пакетов DPI может **замедлять** соединение — искусственно вносить задержки, ограничивать пропускную способность. Пользователь видит «тормозит, но работает», что сложнее диагностировать, чем полный обрыв. 3. **Адаптивное обучение:** DPI не имеет статической базы fingerprint'ов. Он может **обучаться** новым сигнатурам в реальном времени. Если новый fingerprint появился и DPI его пропустил (например, потому что трафика мало), через некоторое время он может начать его блокировать. **Это объясняет паттерн «работало вчера, перестало сегодня»** — DPI потребовалось время, чтобы накопить статистику и обучить классификатор. 4. **Корреляция по нескольким признакам:** DPI может комбинировать fingerprint + SNI + IP + порт + поведение. Если хотя бы один признак совпадает с известной сигнатурой прокси — соединение помечается как подозрительное. ### Баг в encrypted_client_hello Telegram (из статьи) В коде генерации `encrypted_client_hello` у Telegram нашли ошибку: - Формируется нестандартное TLS-расширение с **неверным ID** и **некорректной длиной** - Из-за этого ClientHello Telegram легко матчится ТСПУ - Патч подготовлен, но на момент статьи не смерджен в официальный tdesktop **Этот случай — иллюстрация того, как даже небольшая ошибка в TLS-реализации клиента делает его узнаваемым для DPI.** Применительно к XRay: если клиент (v2rayNG, XRay-core на Android) отправляет ClientHello, который отличается от нормального браузерного, DPI может отфильтровать соединение ещё до того, как XRay сервер успеет проверить REALITY-подпись. ## Меры противодействия 1. **Использовать Reality вместо Fake-TLS/MTProxy** — Reality уже имеет встроенную маскировку под реальный HTTPS 2. **Менять `fingerprint` в клиенте** — `chrome` / `firefox` / `random`. Если провайдер знает fingerprint конкретного браузера, смена маски может помочь 3. **Менять `dest` на сервере** — если DPI блокирует fingerprint клиента для конкретного сайта, смена `reddit.com` на `cloudflare.com` или `microsoft.com` может обойти блокировку (потому что DPI может сверять fingerprint + dest) 4. **Добавлять второй порт** — 8443, 2053, 2096 — на разных портах DPI может работать по-разному 5. **Encrypted Client Hello (ECH)** — скрывает часть параметров TLS-рукопожатия, но пока не везде поддерживается и может блокироваться отдельно 6. **Обновлять клиент** — fingerprint клиента может меняться с версиями v2rayNG/XRay-core ## Эмпирические наблюдения: когда меры не помогают (сессия 2026-07-15) В ходе диагностики на Ростелеком (домашний WiFi) был задокументирован случай, когда **ни одна из стандартных мер не дала результата**: | Мера | Что пробовали | Результат | |------|--------------|-----------| | Смена порта | 443 → 8443 → 50000 | `failed to read client hello` на всех | | Смена dest | reddit.com → microsoft.com → discord.com | `failed to read client hello` на всех | | Смена fingerprint | chrome → random | Без изменений | | Смена shortId | Не пробовали | — | **Контекст:** пользователь Ростелеком, домашний WiFi. Вечером предыдущего дня соединение работало. На следующее утро/день — перестало на всех портах и всех маскирующих доменах. Сервер XRay 26.7.11, клиент Xray-core 26.6.27 (встроен в v2rayNG 2.2.6). Параметры: flow=xtls-rprx-vision, fingerprint=chrome (позже random), encryption=none. **Вывод:** DPI на конкретном провайдере (Ростелеком) может детектить XRay Reality **независимо от порта и маскирующего домена**. Fingerprint клиента (v2rayNG отправляет ClientHello с характерными параметрами XRay-core) является достаточным признаком для блокировки. Это означает, что DPI обучился на fingerprint XRay-core, а не на конкретном сайте или порте. **Ограничение эксперимента:** Не пробовались другие транспорты (gRPC, WebSocket, QUIC), не пробовался Trojan или Shadowsocks на тех же портах. Возможно, блокировка специфична именно для VLESS+Reality+Vision — следующая попытка должна сменить протокол. ### Что пробовать в такой ситуации (от простого к сложному) 1. **Сменить transport** — Reality → WebSocket + TLS (через nginx reverse proxy) → другая сигнатура ClientHello 2. **Сменить протокол** — VLESS → Trojan → другой fingerprint XRay-core 3. **Сменить `fingerprint` на `random`** в клиенте — тогда XRay-core будет генерировать случайный ClientHello каждый раз, что делает fingerprint-анализ бесполезным 4. **Добавить CDN/Cloudflare перед сервером** — если IP провайдера попал в «серые списки», CDN скроет реальный IP 5. **Try AmneziaWG** — использует другой механизм обфускации, не основанный на TLS fingerprint 6. **Try Shadowsocks + v2ray-plugin (WebSocket)** — другая транспортировка, другой fingerprint ### Ключевой вывод Статья про MTProxy — это не про MTProxy. Это про то, что **DPI перешёл на новый уровень анализа**. Fingerprint-фильтрация ClientHello стала реальностью. XRay Reality спроектирован с учётом этого (использует настоящий TLS-сервер), но не застрахован полностью: если ClientHello от клиента выглядит подозрительно, DPI может заблокировать его ещё до REALITY-проверки. **Урок на будущее:** fingerprint клиента XRay-core (даже с `chrome`/`random`) может быть распознан DPI независимо от порта и dest. В такой ситуации нужно менять не параметры Reality, а транспорт/протокол целиком.