Skip to content

REALITY — Xray-core

REALITY — разработанная в Xray альтернатива TLS с публичным сертификатом: во время TLS-рукопожатия сервер выдаёт себя за реальный сторонний сайт, работая прозрачным прокси для неавторизованных клиентов и поднимая авторизованных до настоящей прокси-сессии. Само рукопожатие неотличимо от подключения к имитируемому сайту.

Конфигурация

Задаётся в streamSettings.realitySettings, когда streamSettings.security равно "reality". Одна и та же структура содержит поля и сервера (входящее подключение), и клиента (исходящее); на каждой стороне значима только своя половина параметров.

ПолеТипПо умолчаниюДопустимые значенияОписание
masterKeyLogstring(unset)<file path>Дамп ключей в стиле SSLKEYLOGFILE для отладки. Не включайте в боевой среде.
showboolfalsetrue | falseПечатать подробную информацию о рукопожатии REALITY в журнал ошибок при каждом соединении. Только для диагностики — вывод очень объёмный.
targetjson.RawMessage(use dest)<host:port>Входящее подключение — псевдоним для `dest`. Задавайте одно из двух, не оба.
destjson.RawMessage(required)<host:port>Входящее подключение — цель маскировочного рукопожатия. TLS ClientHello проксируется на этот адрес, когда клиент не является легитимным пиром REALITY; это тот «настоящий» сайт, который увидят наблюдатели.
typestring(auto)tcp | unixВходящее подключение — протокол бэкенда для `dest`. Выводится из формы `dest`.
xveruint6400 | 1 | 2Входящее подключение — версия PROXY protocol, добавляемая при пересылке на `dest`.
serverNames[]string(required)[<hostname>]Входящее подключение — SNI-имена TLS, которые оно принимает. Соединения с другим SNI пересылаются на `dest` (маскировочный путь).
privateKeystring(required)<base64 X25519 private key>Входящее подключение — закрытый ключ X25519. Генерируется командой `xray x25519`.
minClientVerstring(unset)<semver>Входящее подключение — минимальная версия Xray, которую может объявить клиент. Более старые клиенты отклоняются.
maxClientVerstring(unset)<semver>Входящее подключение — максимальная версия Xray, которую может объявить клиент.
maxTimeDiffuint64(unset)<milliseconds>Входящее подключение — максимально допустимое расхождение часов клиента и сервера в миллисекундах. Большее расхождение приводит к отказу в рукопожатии.
shortIds[]string(required)[<hex string>]Входящее подключение — список разрешённых коротких ID (hex, чётной длины, до 16 символов). Пустая запись `""` разрешает клиентов, не объявляющих короткий ID. Обычно каждому авторизованному пользователю выдают уникальный короткий ID.
mldsa65Seedstring(unset)<base64 seed>Входящее подключение — сид постквантовой подписи ML-DSA-65. Сочетается с `mldsa65Verify` у клиентов.
limitFallbackUploadLimitFallback(unset)LimitFallbackВходящее подключение — ограничение скорости в направлении отдачи после перехода авторизованного клиента на реальный прокси. Помогает сделать REALITY неотличимым от медленного легитимного сайта.
limitFallbackDownloadLimitFallback(unset)LimitFallbackВходящее подключение — то же для направления загрузки.
fingerprintstringchromechrome | firefox | safari | edge | 360 | qq | ios | android | random | randomizedИсходящее подключение — отпечаток ClientHello uTLS. Определяет, как ClientHello выглядит на проводе.
serverNamestring(required)<hostname>Исходящее подключение — SNI, отправляемый в ClientHello. Должен совпадать с одним из `serverNames` сервера.
passwordstring(required)<string>Исходящее подключение — пароль REALITY (открытый ключ X25519 плюс тег аутентификации). Генерируется командой `xray reality`.
publicKeystring(unset)<base64 X25519 public key>Исходящее подключение — альтернатива `password`; открытый ключ X25519 сервера напрямую.
shortIdstring""<hex string>Исходящее подключение — короткий ID, объявляемый серверу. Должен входить в список `shortIds` сервера. Пустая строка допустима, только если сервер указал `""`.
mldsa65Verifystring(unset)<base64 verify key>Исходящее подключение — ключ проверки ML-DSA-65, соответствующий `mldsa65Seed` сервера.
spiderXstring(unset)/<path>Исходящее подключение — подсказка-путь для «паука», имитирующая легитимное поведение браузера во время маскировочного рукопожатия.

Исходный код: infra/conf/transport_security.go:27-52 · зафиксировано на v26.7.28 (5ca6f4b)

Генерация ключей

REALITY требует пары ключей X25519. Сгенерируйте её встроенной командой Xray:

sh
$ xray x25519
Private key: <base64-private-key>
Public key:  <base64-public-key>
Password:    <base64-password>

Private key попадает в privateKey сервера. Клиенты используют либо password (рекомендуется — упаковывает открытый ключ вместе с тегом аутентификации), либо напрямую publicKey.

Для постквантовой защиты ML-DSA-65 (необязательно):

sh
$ xray mldsa65
Seed:   <base64-seed>
Verify: <base64-verify-key>

Примеры

Сервер (VLESS + REALITY, имитирующий www.cloudflare.com):

json
{
  "inbounds": [{
    "tag": "vless-reality",
    "listen": "0.0.0.0",
    "port": 443,
    "protocol": "vless",
    "settings": {
      "clients": [{ "id": "<UUID>", "flow": "xtls-rprx-vision" }],
      "decryption": "none"
    },
    "streamSettings": {
      "network": "tcp",
      "security": "reality",
      "realitySettings": {
        "show": false,
        "dest": "www.cloudflare.com:443",
        "xver": 0,
        "serverNames": ["www.cloudflare.com"],
        "privateKey": "<base64-private-key>",
        "shortIds": ["", "0123456789abcdef"]
      }
    }
  }]
}

Клиент, соответствующий серверу выше:

json
{
  "outbounds": [{
    "tag": "vless-reality",
    "protocol": "vless",
    "settings": {
      "address": "your.server.example",
      "port": 443,
      "id": "<UUID>",
      "flow": "xtls-rprx-vision",
      "encryption": "none"
    },
    "streamSettings": {
      "network": "tcp",
      "security": "reality",
      "realitySettings": {
        "fingerprint": "chrome",
        "serverName": "www.cloudflare.com",
        "password": "<base64-password>",
        "shortId": "0123456789abcdef"
      }
    }
  }]
}

Примечания

  • dest — это цель маскировки. Выберите реальный сайт с публично доверенным TLS-сертификатом; для неавторизованных клиентов наблюдатели видят трафик, идущий к этому сайту. Частые варианты: www.cloudflare.com, www.microsoft.com, dl.google.com.
  • serverNames должен содержать SNI, который будут использовать клиенты. Пришедший на сервер трафик с SNI не из списка молча пересылается на dest — это запасной путь, делающий REALITY неотличимым от настоящего сайта.
  • shortIds — различение по пользователям или группам. Каждый авторизованный клиент использует одну запись из списка. Добавьте "" (пустую запись), если хотите разрешить клиентов без короткого ID; для строгого режима опустите её.
  • password предпочтительнее publicKey: он кодирует открытый ключ вместе с дополнительным тегом аутентификации, так что одного украденного открытого ключа недостаточно для аутентификации.
  • limitFallbackUpload / limitFallbackDownload ограничивают пропускную способность авторизованных клиентов после перехода на REALITY. Подгонка этих значений под полосу реального апстрима затрудняет обнаружение REALITY по «отпечатку» пропускной способности.
  • show: true выдаёт подробные журналы каждого рукопожатия REALITY — используйте только для тестирования.

Сравнение с другими ядрами

  • sing-box аккуратно разделяет схему на InboundRealityOptions и OutboundRealityOptions, а цель маскировки вложена в под-блок handshake. См. REALITY — sing-box.
  • mihomo тоже использует две структуры: исходящую RealityOptions (только public-key + short-id) и входящую RealityConfig (серверная сторона с dest, private-key, server-names, short-id, …). См. REALITY — mihomo.

Исходный код: infra/conf/transport_security.go:27-52 · v26.7.28 (5ca6f4b)

Core Tutorial от Argsment