Reality — обман DPI без сертификата

Reality (RPRX, январь 2023) — самый революционный шаг в обходе блокировок за последние 5 лет. Главная идея: не маскироваться под HTTPS, а реально проводить HTTPS-handshake с настоящим чужим сайтом. Только в середине этого handshake клиент и сервер «перехватывают» канал. DPI видит идеальный TLS — потому что он идеальный.

Что узнаешь
Вспомни из прошлых уроков

Reality — прямой ответ на модель противника из урока 5: passive (настоящий JA3 и SNI чужого сайта), active probing (проба видит реальный apple.com), TLS-in-TLS (убран через Vision из урока 6). Он снимает главную зависимость Xray-стека — собственный домен и сертификат (урок 6). Держи это в голове: Reality не «ещё одна маскировка», а закрытие всех трёх эшелонов DPI разом.

1. Проблема, которую решает Reality

До Reality все «маскирующиеся» протоколы (Trojan, VLESS+TLS+WS) имели две слабости:

  1. Нужен настоящий домен и сертификат. Покупка домена, привязка к IP, Let's Encrypt, обновление каждые 90 дней. Каждый «свой» домен в blacklist DPI попадает быстро.
  2. Active probing. DPI может сам подключиться к подозрительному IP и проверить: «а есть ли тут реальный сайт?». Если нет — забанить.

Reality решает оба за раз: SNI указывает на чужой реальный сайт, и сервер Reality, увидев handshake без нужного «приветствия», проксирует handshake на тот самый чужой сайт. Active probe получит ответ настоящего сервера — не от твоего VPN.

2. Как работает Reality — высокоуровневая схема

Reality: процесс установления соединения
Клиент (Xray + Reality) DPI / ТСПУ (видит ВСЁ) Reality-сервер (твой VPS) apple.com (настоящий сайт, dest) ① TCP к IP сервера:443 ② ClientHello, SNI=apple.com DPI: "ок, apple.com — ok" ③ если auth fail → проксирует ClientHello → apple сервер проверяет: расшифровка X25519 KeyShare + valid auth tag? ④ ServerHello (наш, valid TLS 1.3) DPI видит: TLS 1.3 handshake idle ⑤ Certificate apple.com ⑥ кладёт настоящий cert в ответ DPI видит: настоящий apple.com cert! ⑦ Туннель установлен! DPI видит: обычный HTTPS с apple.com
Reality: TLS handshake к чужому сайту, который перехватывает на середине свой сервер

3. Как сервер проверяет «свой/чужой» в первом байте

Это сердце Reality. Никакого пароля в plaintext, никакой явной аутентификации. Используется хитрая схема на X25519:

  1. На сервере сгенерирована пара (server_priv, server_pub). server_pub кладётся в конфиг клиента.
  2. Клиент при handshake генерирует свой ephemeral X25519 e_c. Считает shared = X25519(e_c, server_pub).
  3. Использует shared как ключ для шифрования специального auth-tag, который кладётся в случайное место session_id поля ClientHello (32 байта random, как должно быть). Клиент пишет туда зашифрованный «правильный» магический cookie.
  4. В Key Share extension клиент кладёт свой e_c. Сервер видит его как обычный TLS Key Share — DPI не подозревает.
  5. Сервер получает ClientHello, видит KeyShare, вычисляет shared = X25519(server_priv, e_c), пытается расшифровать session_id. Если magic cookie сошёлся — клиент свой.
  6. Если расшифровка не сошлась (это сторонний запрос, например, active probe DPI) — сервер проксирует ClientHello на dest = apple.com:443 и отдаёт обратно настоящие ответы apple.com. Active probe видит реальный сайт.
Под капотом

Почему это математически невозможно отличить от настоящего TLS

В ClientHello session_id — это произвольные 32 байта, описанные стандартом TLS как «opaque». У реальных браузеров session_id — обычно случайные (или специфический формат). У клиента Reality session_id выглядит как случайный шум (потому что это шифротекст). DPI не может отличить «random» от «зашифрованного random» — это и есть фундамент Reality.

KeyShare X25519 — тоже выглядит как 32 байта random для DPI. Эфемерный pub-key всегда так выглядит. Никакой статистический классификатор не может опознать «не настоящий X25519 KeyShare».

4. ShortIDs — несколько клиентов на одном сервере

Если у тебя 10 пользователей, у каждого свой UUID — как сервер их различает? В Reality для этого есть ShortIDs — короткие (1-8 байт) hex-строки, которые тоже кладутся в зашифрованную часть session_id.

В конфиге сервера:

"shortIds": [
  "",                  // ← пустой = «любой» (на отладке)
  "01ab",              // пользователь 1
  "02cd",              // пользователь 2
  "03ef",              // пользователь 3
  "0a0b0c0d0e0f1011"   // VIP-пользователь, длиннее (8 байт)
]
  

У клиента в конфиге shortId: "01ab" — он его шифрует в session_id. Сервер расшифровал — сравнил с whitelist'ом — пропустил.

5. Какой dest (SNI-цель) выбирать

Это самый важный конфигурационный параметр Reality. К чему предъявляются требования:

Идеальный dest
  1. TLS 1.3 only. Сервер должен поддерживать TLS 1.3 (Reality использует только её для KeyShare extension)
  2. X25519 supported. Должен поддерживать X25519 в KeyShare
  3. HTTP/2 enabled. Для правдоподобия (большинство современных сайтов)
  4. Иностранный сайт. Не российский (чтобы IP не «пингался» внутри РФ — это будет странно). Подходят: apple.com, microsoft.com, amazon.com, cloudflare.com
  5. Существующий сайт. ALPN-handshake должен реально отдавать контент, иначе active probe получит ошибку
  6. НЕ Cloudflare. CF использует тот же IP для тысяч сайтов — если SNI не совпадёт, ответ может прийти странным
  7. Стабильный IP. Не AnyCast-CDN с динамическими IP

В 2024-2025 популярные хорошие dest'ы:

НЕ использовать

6. Полная конфигурация — сервер и клиент

Сервер (Xray-core)

{
  "log": { "loglevel": "warning" },
  "inbounds": [
    {
      "port": 443,                          // ← наружу 443, как у обычного HTTPS
      "protocol": "vless",
      "settings": {
        "clients": [
          {
            "id": "12345678-1234-1234-1234-123456789012",  // ← UUID пользователя
            "flow": "xtls-rprx-vision",                    // ← Vision overlay
            "email": "user1@vpn"
          }
        ],
        "decryption": "none"
      },
      "streamSettings": {
        "network": "tcp",
        "security": "reality",
        "realitySettings": {
          "show": false,
          "dest": "www.microsoft.com:443",                  // ← маскируемся под MS
          "xver": 0,
          "serverNames": ["www.microsoft.com"],             // ← валидные SNI
          "privateKey": "SERVER_PRIVATE_KEY_BASE64",        // ← xray x25519
          "minClientVer": "",
          "maxClientVer": "",
          "maxTimeDiff": 0,
          "shortIds": ["", "01ab", "02cd"]
        }
      }
    }
  ],
  "outbounds": [
    { "protocol": "freedom", "tag": "direct" },
    { "protocol": "blackhole", "tag": "block" }
  ],
  "routing": {
    "rules": [
      { "type": "field", "ip": ["geoip:private"], "outboundTag": "block" }
    ]
  }
}
  

Генерация ключей: xray x25519 — выведет priv/pub keys.

Клиент (Xray / sing-box / NekoBox / v2rayN)

{
  "inbounds": [
    { "port": 10808, "protocol": "socks", "listen": "127.0.0.1" }
  ],
  "outbounds": [
    {
      "protocol": "vless",
      "settings": {
        "vnext": [
          {
            "address": "VPS_IP",                            // ← IP твоего VPS
            "port": 443,
            "users": [
              {
                "id": "12345678-1234-1234-1234-123456789012",
                "flow": "xtls-rprx-vision",
                "encryption": "none"
              }
            ]
          }
        ]
      },
      "streamSettings": {
        "network": "tcp",
        "security": "reality",
        "realitySettings": {
          "serverName": "www.microsoft.com",              // ← маскировка под MS
          "fingerprint": "chrome",                         // ← uTLS под Chrome
          "publicKey": "SERVER_PUBLIC_KEY_BASE64",
          "shortId": "01ab",
          "spiderX": "/"                                   // ← путь спайдеринга (см. ниже)
        }
      }
    }
  ]
}
  

7. SpiderX — финальный штрих маскировки

Когда сервер Reality перехватил handshake, он отдал клиенту сертификат настоящего apple.com. После этого происходит обычный TLS application data. Но клиент НЕ открывает apple.com — он шлёт свой VPN-трафик через VLESS.

Чтобы DPI не заметил «странного поведения» (TLS-handshake с apple.com → дальше нет http-запросов к apple), Xray на стороне клиента эмулирует SpiderX: фоновые HTTP-запросы к настоящему apple.com по разным path. DPI видит: «клиент пошёл на apple.com и листает страницы» — нормально.

spiderX: "/" означает: при подключении делать GET / и эмулировать поведение браузера. Можно настраивать паттерн обхода (что и как часто запрашивать).

8. Слабости Reality

Reality не магия. Несколько ограничений:

Что может пойти не так
  1. IP сервера зачисляется в blacklist. Не по протоколу, а по объёму трафика. Если на твой IP идёт 100 ГБ/сутки — это уже подозрительно, ТСПУ может пометить «вероятно VPN». Reality не защищает от per-IP-блокировок по traffic volume.
  2. Тайминги. SpiderX делает запросы только на handshake. После — длинная сессия с маленькими/большими пакетами. Если у DPI хорошая ML-модель, она может задетектить «не настоящее браузерное поведение». Помогают uTLS + Vision + смешение реального трафика.
  3. Active probing на dest mismatch. Если активный probe из РФ подключится с SNI=apple.com к твоему IP — он получит реальный ответ apple. Но если он подключится с другим SNI к твоему IP (например, ничего не указав, или указав bing.com) — Reality его НЕ обработает (сервер ждёт правильный SNI). Это потенциальный leak. В Xray есть параметр serverNames — список допустимых SNI; всё что не в нём — отвергнуть.
  4. Reality в РФ работает в 2025 потому, что ТСПУ не научилось это всё классифицировать. К 2026-2027 ML-классификация на bidirectional flow станет проблемой даже для Reality. Решения уже разрабатываются (см. урок 14).

9. Почему Reality всё ещё работает в 2026

  1. Снаружи неотличим от настоящего HTTPS. JA3 = настоящий Chrome. SNI = настоящий популярный сайт. Сертификат = настоящий чужой. Никакой статистики, которая могла бы выделить Reality среди «настоящих HTTPS-соединений».
  2. Active probing провален. Probe видит реальный apple.com.
  3. TLS-in-TLS нет. Vision splice убирает overhead и паттерн.
  4. Не нужен домен. Тысячи клиентов могут поднять Reality на любом VPS без domain registration — нечего вносить в blacklist.
  5. Open source, активно развивается. Каждый месяц патчи.

Reality — это текущий S-тир. Других протоколов такого уровня в 2026 нет.

Аналогия

Не поддельный паспорт, а вход через настоящую дверь

Trojan и обычный TLS-камуфляж — это качественная подделка документов: чем лучше подделка, тем дольше живёт, но эксперт (DPI) рано или поздно найдёт признак фальшивки (TLS-in-TLS, чужой JA3). Reality идёт иначе: он реально начинает входить в дверь настоящего здания — проводит подлинное TLS-рукопожатие с apple.com, с его настоящим сертификатом. Охранник (DPI) видит человека, честно входящего к Apple, — придраться не к чему, потому что это НЕ имитация, это Apple. И только в последний миг, уже внутри, «свой» клиент по секретному знаку (X25519-ключ + ShortID) сворачивает к твоему серверу, а чужой (probe) идёт дальше к настоящему Apple и ничего не замечает. Нельзя подделать то, что не подделываешь.

10. Мини-лаба: попробуй прямо сейчас

Ключи Reality и «кражу» чужого TLS можно рассмотреть без поднятия сервера:

# 1. Сгенерируй пару ключей Reality (X25519) — сервер отдаёт публичный клиентам
xray x25519
# Private key: ... / Public key: ...  — та самая асимметрика из урока 2

# 2. Посмотри «жертву маскировки»: реальный TLS-сертификат сайта-донора.
#    Именно ЭТОТ сертификат увидит DPI в твоём Reality-трафике.
openssl s_client -connect www.microsoft.com:443 -servername www.microsoft.com 2>/dev/null \
  | openssl x509 -noout -issuer -subject -dates

# 3. Проверь пригодность донора: нужен TLS 1.3 + HTTP/2 (X25519) и НЕ за Cloudflare-CDN
openssl s_client -connect www.microsoft.com:443 -tls1_3 2>/dev/null | grep -E "Protocol|Cipher"
curl -sI https://www.microsoft.com | grep -iE "server|alt-svc"

# 4. Сгенерируй ShortID (несколько клиентов на одном сервере)
openssl rand -hex 8
Ожидаемый результат

Пункт 1 даст пару ключей — приватный остаётся на сервере, публичный прописывают клиенты (сравни с ролями ключей из урока 2). В пункте 2 ты увидишь ПОДЛИННЫЙ сертификат microsoft.com — это ровно то, что предъявит DPI твой Reality-сервер, поэтому придраться не к чему. Пункт 3 проверяет донора: нужен настоящий TLS 1.3 без чужого CDN впереди (иначе «кража» не сработает). Пункт 4 даёт ShortID — метку, по которой сервер отличает твоих клиентов от случайных проб, идущих к настоящему Microsoft.

11. Задачи самопроверки — реши, потом раскрой ответ

Задача 1. Объясни в двух предложениях, почему active probing, убивший Trojan, бессилен против Reality.

Probe от DPI не предъявляет секретный X25519-ключ и валидный ShortID, поэтому Reality-сервер прозрачно проксирует его на НАСТОЯЩИЙ сайт-донор (например, microsoft.com) — probe видит подлинный сайт с подлинным сертификатом и не находит ничего подозрительного. «Свой» клиент, знающий ключ, в нужный момент перехватывается сервером; отличить их снаружи невозможно, потому что до момента аутентификации всё — настоящий TLS к настоящему сайту.

Задача 2. Почему Reality не нужны ни собственный домен, ни сертификат Let's Encrypt, ни CDN — и какое практическое преимущество это даёт против блокировок?

Reality предъявляет чужой настоящий сертификат (донора), а не свой — регистрировать домен и выпускать сертификат незачем. Практический выигрыш: нечего вносить в чёрный список. Домен можно заблокировать по имени, а тут имени нет — есть только IP VPS и SNI чужого популярного сайта, который цензор блокировать не станет (себе дороже). Тысячи пользователей поднимают Reality на произвольных VPS без единой общей зацепки для блокировки.

Задача 3. Друг выбрал донором (dest/SNI) маленький персональный блог на shared-хостинге за Cloudflare. Назови две причины, почему это плохой выбор.

(1) За Cloudflare/CDN «кража» ломается: ты снимаешь TLS чужого CDN, а не самого сайта — параметры не совпадут, и маскировка станет заметной или неработающей. (2) Непопулярный редкий сайт сам по себе подозрителен: массовый поток «клиентов» к личному блогу — аномалия для статистического эшелона, и такой SNI легко занести в списки. Донор должен быть крупным, всегда живым, с TLS 1.3+X25519 и без чужого CDN впереди (apple.com, microsoft.com и т.п.).

Задача 4. Зачем в Reality нужны ShortID, если аутентификация и так идёт по X25519-ключу?

ShortID позволяет обслуживать нескольких клиентов/группы на одном сервере и различать их: короткая метка в рукопожатии сообщает серверу, что это «свой» и какой именно, до дорогой криптографии, и даёт возможность отзывать доступ выборочно (сменил ShortID — отключил группу), не меняя основную пару ключей. Это удобство эксплуатации и гранулярность, поверх базовой аутентификации ключом.

Задача 5. Reality сегодня — S-тир, но у него есть слабости. Назови хотя бы две и объясни, почему он всё равно работает.

Слабости: (1) статистический эшелон — если внутри туннеля идёт нехарактерный для веб-сёрфинга равномерный поток (большая закачка, стрим), профиль трафика может отличаться от реального визита на сайт-донор; (2) зависимость от «здоровья» донора — если выбранный сайт меняет TLS-параметры или ложится, маскировка деградирует; (3) TCP-природа — на плохих каналах хуже QUIC. Работает потому, что закрывает два самых дешёвых и массовых эшелона (passive и active probing) идеально, а статистику атаковать дорого и чревато ложными срабатываниями на настоящем трафике к популярным сайтам.

12. Словарик урока

Realityмаскировка через подлинный TLS-handshake с чужим сайтом; без своего домена/сертификата
донор · dest / target SNIреальный популярный сайт, чей TLS «одалживается» (apple.com, microsoft.com)
кража рукопожатия · handshake stealingReality реально начинает TLS с донором, перехватывая канал в середине для «своих»
X25519-аутентификациясекретный ключ, по которому сервер узнаёт «своего» клиента среди проб
ShortIDкороткая метка: несколько клиентов/групп на одном сервере, выборочный отзыв
SpiderXдополнительный путь/параметр маскировки запроса к донору
active probing (повтор)проба DPI: у Reality проваливается — ведёт на настоящий сайт-донор
Vision spliceрежим, убирающий TLS-in-TLS оверхед и сигнатуру (из урока 6)
fallback-донорповедение сервера для чужих: прозрачное проксирование на реальный сайт

13. Дальше

Reality — это TCP-стрим. Есть случаи (плохой UDP-канал, мобильник в роуминге, потери), где TCP-туннель страдает. Для этого случая существуют UDP-туннели на QUIC: Hysteria 2, TUIC. Они быстрее на плохих каналах и имеют другой набор противотрюков (port hopping, BBR Brutal). Это урок 08.