Разбор методов детекции, которые работают прямо сейчас. JA3/JA4-отпечатки, поведенческий анализ и архитектура XHTTP, которая закрывает именно эти дыры.

Если твой VLESS+Reality сервер лёг в последние месяцы — ты не один. В сообществах фиксируют волны блокировок, которые раньше не достигали хорошо настроенных Reality-серверов. Мой собственный лёг в январе — и я несколько дней был уверен что дело в конфиге, пока не полез глубже. Дело было не в конфиге.

Сначала про то, как устроен наш противник

ТСПУ работает не как один монолитный фильтр. Это несколько последовательных слоёв проверки, каждый дороже предыдущего по вычислительным ресурсам. Архитектура разумная: зачем гонять весь трафик через ML-классификатор, если можно отсеять 80% на первом байте за микросекунды.

Слой 1: сигнатурный анализ. Первые 16–32 байта пакета сверяются с базой известных паттернов. Чистый Shadowsocks умирает здесь: его первый байт статистически отличается от TLS. OpenVPN — то же самое, характерное рукопожатие, 16 байт, блокировка. VLESS с нормальным TLS эту проверку проходит, первые байты идентичны обычному HTTPS.

Слой 2: TLS-fingerprinting. JA3 — хэш из параметров TLS ClientHello: список cipher suites, расширения, поддерживаемые elliptic curves, форматы точек. Всё конкатенируется и хэшируется в MD5:

JA3 = MD5(SSLVersion, Ciphers, Extensions, EllipticCurves, EllipticCurvePointFormats)

Реальный Chrome 120 на Windows 11 имеет конкретный хэш. Если прокси-клиент использует собственную TLS-библиотеку — его хэш будет другим. Не «похожим на нехороший» — просто другим, и этого достаточно.

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

Слой 3: активное зондирование. Система отправляет к серверу разведчика: пробует HTTP, HTTPS, разные версии TLS. Легитимный сайт отвечает нормально — проходит. Не отвечает или отвечает нетипично — блокировка.

Слой 4: поведенческий анализ. Самый дорогой. Анализируется не содержимое пакетов, а их поведение во времени. Reality проигрывает именно здесь.

JA3/JA4: почему fingerprint: chrome — это не опция, это необходимость

Чтобы понять масштаб проблемы — небольшой эксперимент.

Зайди на scrapfly.io/web-scraping-tools/ja3-fingerprint из обычного Chrome и запомни хэш. Потом подключись через Xray без параметра fingerprint и зайди снова. Хэши будут разными.

Xray без fingerprint: chrome использует стандартную Go-библиотеку crypto/tls. У неё другой набор cipher suites, другой порядок расширений. JA3-хэш Go-клиента хорошо известен и внесён в базы детекции — не потому что кто-то специально охотился на Xray, просто нестандартные TLS-стеки все попадают в базу автоматически.

С "fingerprint": "chrome" Xray использует uTLS — библиотеку, которая копирует ClientHello настоящего браузера побайтно. Это не «похоже на Chrome» — это Chrome.

Нюанс: с 2024 года браузеры начали рандомизировать порядок TLS-расширений, что снизило уникальность JA3 для идентификации конкретной версии браузера. Но для детекции «это не браузер вообще» — работает по-прежнему. Кастомный TLS-стек виден независимо от рандомизации.

Reality: что она закрывала и почему этого стало мало

Reality появилась как ответ на проблему сертификатов. Даже с fingerprint: chrome — TLS-сессия завершается на твоём сервере. DPI делает активное зондирование, получает сертификат, смотрит на ASN — и видит что это не iCloud.

Решение было радикальным: TLS-сессия буквально завершается на реальном сервере Apple или Microsoft. Клиент делает настоящее рукопожатие с настоящим icloud.com, получает настоящий сертификат Apple, верифицированный через реальную цепочку CA. Данные туннеля вшиваются уже в установленную сессию.

С точки зрения первых трёх слоёв детекции: идеальный TLS к Apple. JA3 совпадает. Сертификат настоящий. Активное зондирование возвращает нормальный ответ. В 2022–2023 это работало почти без исключений.

В 2025 году в СПбПУ была защищена работа по детекции XTLS-Reality. Методы там описаны академически, но они перекликаются с тем, что фиксируют пользователи на практике.

Три вектора, которые там разбираются:

GREASE-анализ. GREASE — механизм Chrome для проверки совместимости TLS-серверов: браузер вставляет случайные «мусорные» расширения в ClientHello. Xray с fingerprint: chrome это имитирует — но паттерн имитации не всегда совпадает с тем, что генерирует текущая версия Chrome. Здесь я честно не знаю насколько глубоко ТСПУ сейчас смотрит именно на GREASE — возможно это пока исследовательский вектор, а не боевой. Но в работе он описан.

IP/ASN несоответствие. Если SNI говорит «iCloud», но IP сервера принадлежит датскому хостинг-провайдеру — аномалия видна сразу. Apple держит серверы в конкретных ASN. Хостинг на Hetzner с sni: icloud.com — детектируемо.

Поведение после рукопожатия. Реальное iCloud-соединение от iPhone имеет характерный паттерн: конкретные API-эндпоинты, характерные тайминги, специфичные заголовки. VLESS-туннель с произвольным трафиком ведёт себя иначе: постоянный двунаправленный поток без пауз, нетипичные размеры пакетов, никаких iCloud API-запросов.

Глава, которую обычно не пишут :-)

Рукопожатие у Reality идеальное. Детекция идёт не по нему.

Reality маскирует установку соединения, но не маскирует то, что по этому соединению передаётся после. VLESS-туннель с активными пользователями генерирует трафик-профиль, который с реальным iCloud не имеет ничего общего. Нейросеть, обученная на реальном трафике Apple-сервисов, видит это быстро.

Серверы с высокой нагрузкой падают быстрее не потому что их «нашли» — а потому что трафик-профиль слишком аномальный для заявленного SNI.

XHTTP

XHTTP — транспортный протокол в Xray-core поверх HTTP/2 или HTTP/3. Похоже на WebSocket+TLS, архитектурно — другое.

WebSocket умер по конкретной причине: соединение начинается с HTTP Upgrade, после чего переходит в постоянный двунаправленный поток без характерных HTTP запрос-ответных пар. Этот паттерн детектируется давно и надёжно.

XHTTP разделяет восходящий и нисходящий трафик на отдельные HTTP-транзакции. Каждая транзакция — обычная HTTP-пара с нормальными заголовками и нормальным временем жизни. Статистически неотличимо от браузера, загружающего контент.

Плюс xPaddingBytes — случайный паддинг к пакетам для нормализации их размеров. Классификатор, обученный на распределении размеров пакетов, видит «нормальный» HTTP.

Три режима XHTTP

packet-up — много коротких HTTP-запросов клиент→сервер, одно соединение сервер→клиент. Работает через любой CDN и Nginx. Небольшой оверхед. Стартовый выбор по умолчанию.

stream-up — одно долгоживущее соединение в каждую сторону. Быстрее, но не проходит через все CDN и реверс-прокси. Для прямого соединения без CDN.

stream-one — единое соединение для обоих направлений. Медленнее, но единственный режим совместимый с XTLS-Vision.

auto — клиент выбирает сам. Разумно если не знаешь точно.

Nginx для stream-one требует конкретных директив:

location /your-path/ {
  grpc_pass unix:/dev/shm/xrxh.socket;
  grpc_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  grpc_read_timeout 315s;
  grpc_send_timeout 315s;
}

XHTTP и Reality не конкурируют

Это самое частое заблуждение в статьях на тему. Reality закрывает детекцию на уровне TLS-рукопожатия и активного зондирования. XHTTP закрывает детекцию на уровне поведения соединения после рукопожатия. Это разные слои, не одна задача.

При использовании XHTTP с Reality автоматически выбирается stream-one, если не указать режим явно.

Полные рабочие конфиги

Критически важная деталь перед использованием: XHTTP в активной разработке. Версии Xray на клиенте и сервере обязаны совпадать. Несовпадение даёт либо глюки, либо полную неработоспособность без понятных ошибок. Это не «желательно» — это условие работоспособности.

Генерируем ключи для Reality:

xray x25519
# Выводит: Private key и Public key
# Сохраняем оба

Серверный конфиг (VLESS + XHTTP + Reality):

{
  "inbounds": [{
    "port": 443,
    "protocol": "vless",
    "settings": {
      "clients": [{
        "id": "your-uuid-here"
      }],
      "decryption": "none"
    },
    "streamSettings": {
      "network": "xhttp",
      "security": "reality",
      "realitySettings": {
        "show": false,
        "dest": "www.microsoft.com:443",
        "xver": 0,
        "serverNames": ["www.microsoft.com"],
        "privateKey": "<PRIVATE_KEY>",
        "shortIds": ["<SHORT_ID>"]
      },
      "xhttpSettings": {
        "path": "/api/v1/data",
        "mode": "auto",
        "extra": {
          "xPaddingBytes": "100-1000"
        }
      }
    },
    "sniffing": {
      "enabled": true,
      "destOverride": ["http", "tls", "quic"]
    }
  }]
}

Клиентский конфиг:

{
  "outbounds": [{
    "protocol": "vless",
    "settings": {
      "vnext": [{
        "address": "your.domain.com",
        "port": 443,
        "users": [{
          "id": "your-uuid-here",
          "encryption": "none"
        }]
      }]
    },
    "streamSettings": {
      "network": "xhttp",
      "security": "reality",
      "realitySettings": {
        "serverName": "www.microsoft.com",
        "fingerprint": "chrome",
        "shortId": "<SHORT_ID>",
        "publicKey": "<PUBLIC_KEY>"
      },
      "xhttpSettings": {
        "path": "/api/v1/data",
        "mode": "auto",
        "extra": {
          "xPaddingBytes": "100-1000"
        }
      }
    }
  }]
}

Вариант с XTLS-Vision (stream-one + Vision):

// Сервер — clients добавляем flow
"clients": [{
  "id": "your-uuid-here",
  "flow": "xtls-rprx-vision"
}]

// xhttpSettings меняем mode
"xhttpSettings": {
  "path": "/api/v1/data",
  "mode": "stream-one"
}
// Клиент — users добавляем flow
"users": [{
  "id": "your-uuid-here",
  "encryption": "none",
  "flow": "xtls-rprx-vision"
}]

Про выбор SNI-донора

Правило одно: реальный сервис с высоким трафиком в том же регионе, где стоит сервер. Хорошие доноры для Европы (и российских пользователей): github.com (стабильный, хорошо известный Microsoft Azure, никаких российских серверов с 2022 года), www.twitch.tv (высокий трафик, AWS, отсутствие российских PoP) ну и microsoft.com остаётся хорошим кандидатом: тот же большой трафик и глобальный CDN с PoP везде. Apple.com это плохой донор несмотря на репутацию: Apple держит IP в собственных ASN, несоответствие между сертификатом и ASN хостинга заметно сразу. Любой мелкий сайт — по той же причине.

Как проверить что всё работает

JA3-проверка: подключись через прокси и зайди на scrapfly.io/web-scraping-tools/ja3-fingerprint. Отпечаток должен совпадать с обычным Chrome без прокси.

Активное зондирование: с другого IP сделай прямой curl:

curl -v https://your.domain.com \
  --resolve your.domain.com:443:<YOUR_IP>

Должен получить нормальный HTTP-ответ, не TLS-ошибку.

Поведенческий профиль: через несколько недель работы посмотри на трафик-статистику сервера. Если входящий и исходящий примерно равны при обычном браузинге — аномалия. У реального веб-сервера исходящий трафик сильно превышает входящий.

Сравнение подходов в 2026-м

Параметр

VLESS + Reality

VLESS + XHTTP

VLESS + XHTTP + Reality

TLS-отпечаток

Идеальный

Хороший (uTLS)

Идеальный

Активное зондирование

Выдерживает

Выдерживает

Выдерживает

Поведенческий анализ

Уязвим при нагрузке

Устойчив

Устойчив

Работа через CDN

Нет

Да (packet-up)

Частично

Совместимость с Vision

Да

Только stream-one

Только stream-one

Сложность настройки

Средняя

Средняя

Выше средней

Устойчивость 2026

Снижается

Растёт

Лучшая из доступных

*мнение автора

Конфиги выше. Удачи.

¹ Автор данной статьи использовал для её написания зарубежный браузер, зарубежный процессор и протокол TLS, разработанный в США. Все упомянутые инструменты предназначены исключительно для изучения сетевых технологий в образовательных целях. Любое совпадение с реальным обходом блокировок случайно и не является целью публикации.

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