Files
networking-proxy/references/tls-fingerprint-dpi-detection.md
2026-09-06 13:51:04 +00:00

14 KiB
Raw Permalink Blame History

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:

  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

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-матчинга:

  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, а транспорт/протокол целиком.