Как устроен обмен ключами в Reality: x25519, shortId и зачем серверу «чужой» сертификат
#реклама. Я Вадим, разработчик сервиса Unlimited VPN, и в конце статьи расскажу о нём. Основная часть — концептуальный разбор протокола REALITY по открытой документации и исходникам проекта Xray-core. Это не описание вну
#реклама. Я Вадим, разработчик сервиса Unlimited VPN, и в конце статьи расскажу о нём. Основная часть — концептуальный разбор протокола REALITY по открытой документации и исходникам проекта Xray-core. Это не описание внутренней кухни нашего сервиса, а объяснение того, как механизм задуман авторами.
Проблема, которую решает Reality
Классический VLESS поверх TLS требует собственного домена и настоящего сертификата. Сторонний наблюдатель видит рукопожатие с малоизвестным сайтом, и если зайти на этот адрес браузером, часто обнаруживается заглушка. Такой сервер легко отличить от обычного веб-ресурса.
Reality подходит с другой стороны: сервер не притворяется сайтом, он буквально перенаправляет «посторонних» на настоящий популярный сайт. Для внешнего проверяющего соединение выглядит как обращение к реальному ресурсу с его подлинным сертификатом.
Что такое x25519 и откуда берутся ключи
x25519 — функция согласования ключей Диффи — Хеллмана на эллиптической кривой Curve25519. У каждой стороны есть закрытый ключ и вычисленный из него открытый. Если клиент знает открытый ключ сервера, а сервер — открытый ключ клиента, обе стороны независимо вычисляют один и тот же общий секрет, ни разу не передав его по сети.
В Xray пара ключей сервера генерируется командой xray x25519. Закрытый ключ остаётся в конфигурации сервера, открытый (в клиентах он часто называется publicKey или pbk) попадает в ссылку подключения. Важно понимать: открытый ключ не секретен, но без него клиент не сможет доказать серверу, что он «свой».
Как клиент подаёт сигнал внутри обычного TLS
Рукопожатие TLS 1.3 начинается с сообщения ClientHello. В нём уже есть поле key_share с эфемерным открытым ключом x25519 — так устроен сам TLS, это не изобретение Reality. Клиент Reality использует этот же эфемерный ключ и открытый ключ сервера, чтобы вычислить общий секрет.
Дальше, согласно описанию в репозитории, из этого секрета выводится ключ, которым шифруется небольшой фрагмент данных, помещаемый в поле session_id ClientHello. Туда входят версия клиента, отметка времени и shortId. Для постороннего глаза session_id — просто 32 случайных байта, как и в любом другом браузерном рукопожатии.
Сервер, получив ClientHello, повторяет вычисление со своей стороны своим закрытым ключом. Если расшифровка удалась, время укладывается в допустимое окно, а shortId есть в списке разрешённых — значит, пришёл легитимный клиент.
Зачем нужен shortId
shortId — короткая шестнадцатеричная строка, которую администратор задаёт в конфиге сервера (список shortIds). По сути это дополнительный идентификатор: можно выдать разным группам клиентов разные значения и при необходимости отключать их по отдельности, не меняя пару ключей. Пустая строка тоже допустима, но тогда эта дополнительная граница исчезает. Если в ссылке опечатка в sid, сервер просто не признает клиента — один из типичных случаев, когда «всё настроено, но не работает».
«Чужой» сертификат: роль dest и serverNames
Самая необычная часть Reality — параметры dest и serverNames. В dest указывается адрес реального стороннего сайта с поддержкой TLS 1.3 и HTTP/2, а в serverNames — допустимые имена (SNI), которые клиент может указать.
Если ClientHello не прошёл проверку, сервер не рвёт соединение и не показывает ошибку. Он прозрачно проксирует трафик на dest, и проверяющий получает настоящий сертификат настоящего сайта. Никакой заглушки, никакого самоподписанного сертификата — именно поэтому активное зондирование мало что даёт.
Если же клиент опознан, сервер завершает рукопожатие сам. Документация описывает это так: сервер выдаёт «временный» сертификат, подпись которого клиент проверяет с помощью того же общего секрета. Это защищает клиента от подмены посредником: человек посередине не знает закрытого ключа сервера и не сможет корректно подписать ответ.
Отпечаток клиента: параметр fingerprint
Ещё одна деталь — fingerprint (fp), например chrome или firefox. Клиент Xray использует библиотеку uTLS, чтобы ClientHello по набору расширений и их порядку был похож на ClientHello популярного браузера. Иначе сам факт нестандартного рукопожатия выдавал бы Go-приложение.
Что из этого следует на практике
- Ошибка в
pbkилиsidвыглядит как «нет соединения», хотя сервер жив. - Неправильные системные часы ломают проверку отметки времени.
- SNI в ссылке должен совпадать с одним из
serverNamesна сервере. - Выбор
dest— ответственность администратора: сайт должен поддерживать TLS 1.3 и быть доступен с сервера.
Именно поэтому большинство клиентов принимают готовую ссылку vless:// или подписку: все эти параметры приходят одним пакетом и вручную ничего вбивать не нужно.
О сервисе (реклама)
Unlimited VPN — мой проект, работающий на VLESS Reality. Серверы расположены в Чехии. Подключение через приложения Happ или v2RayTun на iOS, Android, Windows, macOS и Android TV. Есть пробный период на 3 дня без привязки карты.
- Бот: https://t.me/Vpn_UnlimitedBot
- Канал: https://t.me/UnlimitedVPN_rus
- Поддержка: @UnlimitedVPN_Jorge
Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.