Модератор: вероятно, при создании данной статьи использовался ИИ. Объёмы и профиль использования известны только автору.

Пошаговый разбор того, как ТСПУ анализирует трафик от первого SYN до поведенческого ML. С конкретными числами, реальными алгоритмами и объяснением почему одни протоколы умирают на первом байте, а другие живут месяцами.

Большинство объяснений про DPI звучат так: «система смотрит на пакеты и блокирует плохие». Примерно как объяснить работу компилятора словами «берёт код и делает программу» формально не ложь, но понять из этого что-либо невозможно.

Ниже то, что реально происходит с пакетом от момента выхода с твоего устройства до момента, когда ТСПУ принимает решение. Пошагово, с числами.

Нулевой момент: SYN-пакет

Ты нажимаешь Enter. Браузер или прокси-клиент отправляет TCP SYN на удалённый сервер.

В пакете: IP-заголовок (твой IP, IP назначения, TTL, протокол) и TCP-заголовок (порты, флаг SYN, sequence number, размер окна, TCP-опции). Данных приложения нет вообще — это просто «хочу соединиться».

ТСПУ на этом этапе уже смотрит, но не блокирует. Создаёт запись в таблице соединений: IP источника, IP назначения, порт, время начала. По наблюдениям сообщества ntc.party (для входа возможно потребуются танцы с бубном), первые пять пакетов соединения проходят без активного вмешательства — система собирает данные.

Пакеты 1–5: сбор контекста

За первые пять пакетов ТСПУ собирает базовый профиль соединения. Три вещи интересуют её здесь больше всего.

TTL. Windows отправляет TTL=128, Linux — 64, некоторые устройства — 255. Пакет с TTL=63 прошёл через один хоп от отправителя, TTL=62 через два. Это даёт приблизительную топологию между тобой и сервером. Нужно это для одного: детекции fake-пакетов. Zapret и аналогичные инструменты отправляют поддельные пакеты с намеренно заниженным TTL чтобы они доехали до ТСПУ, но не доехали до реального сервера. ТСПУ научилась это видеть.

TCP-опции. В SYN-пакете: MSS, Window Scale, SACK, Timestamps. Их набор и порядок — отдельный fingerprint. Linux-ядро отправляет один набор, Windows другой, iOS третий. Если заявленная ОС и реальный набор опций не совпадают — аномалия.

Размер первого пакета данных. Если первый содержательный пакет после рукопожатия короче 83 байт — подозрительно. TLS ClientHello намного длиннее. Очень короткий первый пакет: либо кастомный протокол, либо намеренное разбиение для обхода DPI.

Байты 0–5: протокольный маркер

Первые несколько байт данных приложения — самая быстрая проверка. Буквально memcmp() против таблицы паттернов.

TLS ClientHello начинается строго так:

16 03 01 xx xx 01 00 xx xx xx 03 03...

0x16 — Content Type: Handshake. 0x03 0x01 — TLS-версия (legacy-поле, всегда 1.0). 0x01 — Handshake Type: ClientHello. 0x03 0x03 — TLS 1.3 внутри ClientHello.

OpenVPN начинается иначе. Shadowsocks без обфускации выглядит как статистически случайные байты — что само по себе маркер. WireGuard имеет характерный UDP-заголовок. SSH начинается с SSH-2.0-.

Работает за микросекунды, стоит почти ничего, убивает OpenVPN, чистый WireGuard, SSH-туннели и старые Shadowsocks. VLESS с TLS эту проверку проходит — первые байты идентичны любому HTTPS.

Байты 6–300: TLS ClientHello и JA3

ClientHello — самый информативный пакет для детектора. Он содержит список cipher suites, список TLS-расширений с их содержимым, поддерживаемые elliptic curves, форматы точек, SNI в открытом виде, ALPN и GREASE-значения (если это настоящий Chrome).

Из всего этого вычисляется JA3-хэш:

JA3 = MD5(
  SSLVersion,
  Ciphers,          # без GREASE-значений
  Extensions,       # без GREASE, без padding (21)
  EllipticCurves,
  EllipticCurvePointFormats
)

TLS Fingerprinting with JA3 and JA3S - Salesforce Engineering Blog — рекомендую ознакомиться. Реальный Chrome 120 на Windows 11 даёт конкретный хэш. Go-стандартная crypto/tls без uTLS — другой. Этот хэш известен и внесён в базы детекции.

JA4 — более новая версия (FoxIO, 2023): менее чувствителен к порядку расширений, разделяет клиентскую и серверную части, даёт более стабильный отпечаток. DPI-системы переходят на него.

SNI в ClientHello — открытый текст даже в TLS 1.3. Если SNI = icloud.com, а IP назначения принадлежит нидерландскому хостингу — несоответствие видно сразу.

ALPN — протокол приложения. Настоящий браузер предлагает h2 и http/1.1. Прокси-клиент без правильной настройки иногда не включает ALPN вообще — и это тоже аномалия.

Байты 300–3000: ServerHello и сертификат

Сервер отвечает ServerHello, потом Certificate. В сертификате три вещи интересны детектору.

Common Name и Subject Alternative Names. SNI в ClientHello говорил icloud.com значит сертификат должен быть Apple. Если пришёл Let's Encrypt на случайный домен — не совпадает.

Certificate Transparency Logs. Вс�� публичные TLS-сертификаты логируются в CT Logs. Существует ли этот сертификат? Выпущен ли на этот домен? Для самоподписанных ответ «нет».

ASN сервера против ожидаемого ASN домена. Apple держит серверы в AS714. Microsoft в AS8075. Сертификат говорит «я Microsoft», а пакеты приходят из AS24940 (Hetzner) — детектируемое несоответствие. Reality закрывает эту проблему полностью: TLS-сессия завершается на настоящем сервере Apple или Microsoft, сертификат настоящий, ASN совпадает.

Байты 3000–16 000: первые данные приложения

После завершения TLS-рукопожатия начинается зашифрованный трафик приложения. Содержимое недоступно. Но анализ продолжается — по метаданным потока.

Размеры пакетов. У браузерного HTTPS-трафика характерное распределение: HTTP-запросы маленькие (заголовки, GET), HTTP-ответы большие (контент). Асимметричный паттерн с пиками вокруг конкретных значений. Туннель с видео внутри — все пакеты близко к MTU (1400–1500 байт), равномерно. Туннель с интерактивным трафиком — мелкие пакеты в обоих направлениях. Ни то ни другое не похоже на браузерный HTTP.

Межпакетные интервалы. Браузер делает паузы: загрузил HTML — парсит, загружает CSS — парсит, загружает JS. Паузы десятки-сотни миллисекунд, с характерным распределением. VLESS-туннель под нагрузкой гонит данные непрерывно.

Соотношение входящего и исходящего. При обычном браузинге исходящий трафик намного меньше входящего, типичное соотношение 1:10 или 1:20. Туннель, по которому пользователь активно что-то отправляет, нарушает это соотношение.

Продолжительность соединения. Реальный браузер открывает HTTPS, загружает страни��у, держит несколько минут через keep-alive, закрывает. VLESS держит соединение открытым часами. Persistent connection к «iCloud» без единого характерного iCloud API-запроса — аномалия.

После 16 КБ: поведенческий ML

К этому моменту собрано достаточно для ML-классификатора.

Классификатор смотрит на ритм пакетов: реальный пользователь читает статью — загрузил страницу, затих на минуту, прокрутил, снова всплеск. Туннель под нагрузкой: равномерный поток без пауз.

На энтропию данных: зашифрованные данные высокоэнтропийны, но степень равномерности энтропии между пакетами у разных протоколов отличается. Туннель с несколькими слоями шифрования даёт другой энтропийный профиль, чем обычный HTTPS.

На паттерны мультиплексирования: HTTP/2 мультиплексирует несколько стримов в одно соединение. У реального браузера несколько параллельных стримов разного размера и разной продолжительности. Туннель, который гонит весь пользовательский трафик в один HTTP/2-поток, выглядит иначе.

Точность ML-классификаторов в лабораторных условиях достигает 95–99% для Shadowsocks и VMess. В продакшне ниже, ложные срабатывания дорого стоят. Но тренд понятен: система обучается непрерывно на реальном трафике.

Как блокировка срабатывает технически

Три метода, каждый со своим поведением.

TCP RST injection. ТСПУ вставляет в поток RST-пакет. Обе стороны получают сигнал «соединение разорвано» и закрывают его. Быстро и дёшево. Обходится через проверку sequence numbers — RST с неправильным числом клиент игнорирует.

Дроп пакетов. Пакет не доходит до назначения без уведомления сторон. Соединение зависает, потом таймаут. Сложнее обойти, потому что нет явного сигнала.

Замедление. Трафик намеренно throttle-ится: задержки, потери. Именно так работало замедление Twitter и YouTube — не блокировка, а деградация до состояния где пользоваться невозможно.

Как это знание применять

Каждая защита закрывает конкретный слой:

  • fingerprint: chrome в Xray — закрывает JA3-детекцию на уровне байт 6–300

  • Reality — закрывает несоответствие сертификата и ASN

  • XHTTP — закрывает поведенческую детекцию через нормализацию паттерна трафика

  • xPaddingBytes — нормализует распределение размеров пакетов

  • Правильный SNI-донор — закрывает IP/ASN несоответствие

Ни один инструмент в одиночку все слои не закрывает.

Неудобная деталь

Активный DPI стоит в разрыве сети и обрабатывает каждый пакет в реальном времени. Это даёт добавочный latency — на практике 1–5ms для большинства соединений. Для обычного пользователя незаметно, но статистически измеримо.

Есть инструменты, которые детектируют ТСПУ именно по этому признаку: отправляют специально сформированные пакеты и смотрят, изменился ли паттерн задержек. Работает.

¹ Редакция напоминает: изучение принципов работы DPI является потенциально опасным занятием, так как приводит к пониманию того, как именно устроена система стоимостью 20+ млрд рублей из федерального бюджета. Эти знания могут вызвать нежелательные побочные эффекты: критическое мышление, технический суверенитет и стойкое ощущение что деньги потрачены как-то не туда. Проконсультируйтесь с Роскомнадзором перед применением.

Если есть идеи для разбора, нашёл ошибку
или хочешь предложить тему — пиши на
aleksandr@murzin.digital Отвечаю.