14 KiB
TLS Fingerprint — DPI Detection Technique
Источник
Статья на Хабре: Конец удобства? Почему MTProxy начал ломаться (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:
- Принимает ClientHello от клиента
- Проверяет REALITY-подпись (publicKey + shortId + время)
- Если подпись невалидна — проксирует соединение на реальный сервер (dest), как обычный HTTPS
- Если подпись валидна — расшифровывает VLESS-трафик
Разница с MTProxy: MTProxy использует Fake-TLS — сам отправляет поддельный ServerHello, не обращаясь к реальному серверу. У Reality — настоящий TLS-сервер на backend'е, поэтому поведение трафика после рукопожатия неотличимо от браузерного.
Почему это важно для диагностики
Когда в логах XRay появляется REALITY: failed to read client hello, это может быть следствием:
- Неверный publicKey/shortId в клиенте — DPI не при чём, чисто конфигурационная проблема
- DPI обрезает ClientHello на уровне сети — пакет приходит повреждённым/обрезанным
- Клиент отправляет 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
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 не похож на браузерный?<br/>Дропаем/инжектим RST
DPI->>Client: RST (поддельный)
Проявление: failed to read client hello в логах сервера, при этом TCP SYN успешно доходит.
Вариант B — Деградация после установки соединения
DPI пропускает ClientHello, но после установки REALITY-сессии анализирует поведение трафика. Если трафик не похож на HTTPS — начинает дропать пакеты.
Проявление: соединение устанавливается, работает несколько секунд/минут, потом обрывается.
Дополнительные механизмы DPI из статьи
Статья описывает несколько техник DPI, которые выходят за рамки простого fingerprint-матчинга:
-
Поведенческий анализ после соединения: DPI может пропустить ClientHello, установить TLS-сессию, но затем анализировать паттерны трафика (размеры пакетов, частоту, направление). Если трафик не похож на HTTPS-сёрфинг (например, идёт постоянный поток данных без видимых HTTP-запросов), DPI начинает дропать или деградировать соединение.
-
Деградация (throttling) вместо блокировки: Вместо RST или дропа пакетов DPI может замедлять соединение — искусственно вносить задержки, ограничивать пропускную способность. Пользователь видит «тормозит, но работает», что сложнее диагностировать, чем полный обрыв.
-
Адаптивное обучение: DPI не имеет статической базы fingerprint'ов. Он может обучаться новым сигнатурам в реальном времени. Если новый fingerprint появился и DPI его пропустил (например, потому что трафика мало), через некоторое время он может начать его блокировать. Это объясняет паттерн «работало вчера, перестало сегодня» — DPI потребовалось время, чтобы накопить статистику и обучить классификатор.
-
Корреляция по нескольким признакам: 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-подпись.
Меры противодействия
- Использовать Reality вместо Fake-TLS/MTProxy — Reality уже имеет встроенную маскировку под реальный HTTPS
- Менять
fingerprintв клиенте —chrome/firefox/random. Если провайдер знает fingerprint конкретного браузера, смена маски может помочь - Менять
destна сервере — если DPI блокирует fingerprint клиента для конкретного сайта, сменаreddit.comнаcloudflare.comилиmicrosoft.comможет обойти блокировку (потому что DPI может сверять fingerprint + dest) - Добавлять второй порт — 8443, 2053, 2096 — на разных портах DPI может работать по-разному
- Encrypted Client Hello (ECH) — скрывает часть параметров TLS-рукопожатия, но пока не везде поддерживается и может блокироваться отдельно
- Обновлять клиент — 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 — следующая попытка должна сменить протокол.
Что пробовать в такой ситуации (от простого к сложному)
- Сменить transport — Reality → WebSocket + TLS (через nginx reverse proxy) → другая сигнатура ClientHello
- Сменить протокол — VLESS → Trojan → другой fingerprint XRay-core
- Сменить
fingerprintнаrandomв клиенте — тогда XRay-core будет генерировать случайный ClientHello каждый раз, что делает fingerprint-анализ бесполезным - Добавить CDN/Cloudflare перед сервером — если IP провайдера попал в «серые списки», CDN скроет реальный IP
- Try AmneziaWG — использует другой механизм обфускации, не основанный на TLS fingerprint
- 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, а транспорт/протокол целиком.