# 🎯 XTLS и Vision: что это и чем отличается от VLESS и REALITY
> [!info] О чём заметка
> Разбор того, что такое **XTLS** и режим **Vision** (`xtls-rprx-vision`) в [[xray/project-x|Xray-core]], и — главное — чем они отличаются от протокола [[xray/vless|VLESS]] и от [[xray/reality|REALITY]]. Частый вопрос: «XTLS, Vision, REALITY — это одно и то же или разные вещи?». Короткий ответ: **разные вещи на разных уровнях**, которые обычно работают вместе. Разбор основан на чтении исходного кода `proxy/proxy.go` (файл, где живёт вся механика Vision).
## TL;DR
- **VLESS**, **XTLS** и **REALITY** — это **три разные вещи на трёх разных уровнях**, а не синонимы:
- **VLESS** — *протокол* (что переносим): переносит UUID-аутентификацию и опции.
- **XTLS / Vision** — *flow-режим* (как оптимизируем поток): убирает двойное шифрование «TLS-in-TLS» и маскирует длины пакетов.
- **REALITY** — *слой безопасности* (чем шифруем снаружи): замена TLS, маскирующая сервер под чужой сайт.
- **XTLS — это НЕ шифр и не протокол.** Это механизм управления потоком (flow-control) *поверх уже установленного* TLS или REALITY.
- **Vision** (`xtls-rprx-vision`) — единственный живой режим XTLS на 2026 год. Три старых поколения (`origin` → `direct` → `splice`) удалены из кода в версии v1.8.0 (март 2023); `splice` при этом сохранён как внутренняя оптимизация Vision, а не отдельный flow.
- **Причина замены — не «дыра», а детект.** Отдельной уязвимости (CVE) на старые режимы нет; их вытеснили, потому что они не маскировали вложенное TLS-рукопожатие (TLS-in-TLS), а Vision маскирует длины первых пакетов.
- **Vision — не невидимость.** Работа USENIX Security 2024 называет `xtls-rprx-vision` поимённо как схему, которую детектор вложенного хендшейка обходит: паддинг прячет длины пакетов, но не форму трафика в целом.
- Рабочая связка выглядит так: **VLESS + `flow=xtls-rprx-vision` + `security=reality` (или `tls`)** — три независимые оси, которые комбинируются.
## Три уровня: почему это не синонимы
Самая частая путаница — считать VLESS, XTLS и REALITY названиями одного и того же. На деле это три ортогональных (независимых) слоя, каждый отвечает за свою задачу. В коде Xray они и разнесены по разным местам: VLESS живёт в `proxy/vless/`, механика Vision — в `proxy/proxy.go`, REALITY — в `transport/internet/reality/`.
| Слой | Что это | За что отвечает | Значение в конфиге |
|---|---|---|---|
| **VLESS** | Протокол | Аутентификация (UUID) и маршрутизация | `protocol: vless` |
| **XTLS / Vision** | Flow-режим | Убрать TLS-in-TLS, спрятать длины пакетов | `flow: xtls-rprx-vision` |
| **REALITY** | Слой безопасности | Шифрование + маскировка под чужой сайт | `security: reality` |
Каждый из этих слоёв разобран в своей заметке: [[xray/vless|VLESS]], [[xray/reality|REALITY]] и сам XTLS/Vision — ниже.
Проще говоря: представь посылку. **VLESS** — это адрес и подпись на посылке (кто отправитель, куда нести). **REALITY** — это упаковка, которая делает посылку неотличимой от чужой обычной коробки. **XTLS/Vision** — это правило «не заворачивать уже запечатанную коробку во вторую обёртку, а нести как есть». Три разные роли, и все три нужны одновременно.
## Три значения слова «XTLS» — не путать
Само слово «XTLS» перегружено и означает разные вещи в зависимости от контекста. Из-за буквы «TLS» в названии его часто принимают за какой-то вариант шифрования — это неверно. Разведём три значения:
| «XTLS» в смысле | Что это | Пример употребления |
|---|---|---|
| **Организация / сообщество** | GitHub-организация [github.com/XTLS](https://github.com/XTLS) — «зонтик» проекта [[xray/project-x\|Project X]]. Под ней живут репозитории Xray-core, REALITY, Xray-install и др. | «issue в репозитории XTLS», «команда XTLS» |
| **Технология (flow-control)** | Механизм оптимизации потока `xtls-rprx-*`, который убирает двойное шифрование TLS-in-TLS. **Не шифрование** — работает поверх уже установленного TLS/REALITY. | «включить XTLS», `flow: xtls-rprx-vision` |
| **Vision** (частный случай технологии) | Единственная живая реализация flow-механизма на 2026 год. | `xtls-rprx-vision` |
Проще говоря: **XTLS-организация** — это кто пишет код (люди и репозитории), а **XTLS-технология** — это что именно они придумали (приём ускорения трафика). Одно и то же имя, два совершенно разных смысла. Дальше в этой заметке «XTLS» — везде про технологию, если явно не сказано «организация».
> [!warning] XTLS ≠ шифрование, несмотря на «TLS» в названии
> Ни в одном из значений XTLS не является шифром или отдельным протоколом шифрования. Организация XTLS разрабатывает разные технологии (в том числе [[xray/reality|REALITY]] — вот он как раз слой безопасности). А технология XTLS (flow-control) шифрованием не занимается вовсе — она лишь решает, как эффективнее передать **уже зашифрованный** кем-то другим поток. Путаница «XTLS — это такой особый TLS/шифр» — самая частая ошибка новичка.
## Что такое XTLS-технология (и почему это не шифрование)
Ключевой факт, который снимает половину путаницы: **XTLS ничего не шифрует.** Шифрованием занимается слой ниже — TLS 1.3 или REALITY. XTLS — это механизм flow-control, который *наблюдает* за уже зашифрованным потоком и решает, как его эффективнее передать.
Проблема, которую решает XTLS, — **«TLS-in-TLS» (двойное шифрование)**. Когда обычный прокси заворачивает пользовательский HTTPS-трафик (уже зашифрованный первым TLS) во второй TLS-туннель до сервера, получается вложенность: TLS внутри TLS. Это, во-первых, лишняя нагрузка на процессор, а во-вторых — характерная сигнатура, по которой DPI отличает прокси от обычного HTTPS (у вложенного TLS специфические размеры и тайминги записей).
Идея XTLS: раз внутренний поток и так уже зашифрован настоящим TLS 1.3, после рукопожатия внешний слой можно **не шифровать повторно**, а передавать внутренние TLS-записи напрямую. В коде это отражено комментарием в `proxy/proxy.go`: `TrafficState ... is used by XTLS to determine if switch to raw copy mode` — то есть XTLS отслеживает соединение, чтобы понять, когда переключиться в режим «сырого копирования».
## Vision: как это работает в байтах
**Vision** (`xtls-rprx-vision`) — конкретная и единственная сегодня реализация XTLS. Задаётся значением поля `flow` в VLESS. Технически это пара «обёрток» вокруг потока — `VisionReader` и `VisionWriter` в `proxy/proxy.go`, — которые делают две вещи.
### 1. Паддинг первых пакетов (сокрытие длин)
Пока идёт TLS-рукопожатие, Vision добавляет к пакетам случайный **паддинг** (заполнитель) — функция `XtlsPadding`. Каждый блок получает короткий заголовок (до 21 байта: 16 байт UUID в самом первом пакете плюс 5 байт «команда + длина контента (2 байта) + длина паддинга (2 байта)»), а следом дописываются случайные байты. Цель — размыть характерные длины VLESS-заголовка и TLS-хендшейка, чтобы DPI не мог опознать прокси по размеру первых пакетов. В коде так и написано: «add padding to eliminate length signature during tls handshake».
Пороги паддинга параметризованы массивом `testseed`, по умолчанию `{900, 500, 900, 256}`. Логика по коду: если содержимого меньше 900 байт (и включён длинный паддинг), блок добивается до `900 + случайное(0…500) − длина_контента` — то есть суммарно примерно **900–1400 байт**; иначе добавляется просто 0–255 случайных байт. Именно поэтому «магическое число ~900» реально: это одновременно и порог «короткого» контента, и базовое смещение длинного паддинга.
Зачем это нужно, понятнее на разборе первых пяти пакетов любого прокси-соединения с TLS-целью. Даже когда внешний TLS взломать нельзя, цензор может опознать прокси по **длинам** этих пакетов:
1. Прокси-клиент → прокси-сервер: «цель — Google, вот мой UUID» — очень короткий.
2. Прокси-сервер → прокси-клиент: «принял, отправляй данные» — очень короткий, почти фиксированный.
3. Браузер → цель: TLS ClientHello — короткий, почти единственная переменная — SNI.
4. Цель → браузер: TLS ServerHello + сертификат — длинный, сильно варьируется.
5. Браузер → цель: короткий.
Короткие пакеты 1, 2, 3, 5 с очень узнаваемыми длинами — это и есть сигнатура. Vision решает проблему **прицельно**: не заваливает паддингом всё подряд (как наивное случайное заполнение), а по анализу внутреннего трафика **добивает именно характерные пакеты рукопожатия до диапазона примерно 900–1400 байт**. Так короткие служебные пакеты перестают выделяться, а где кончается служебная информация прокси и начинается полезный трафик — на проводе не видно.
### 2. Переход в прямое копирование (direct copy / splice)
Как только Vision убеждается, что внутри туннеля пошёл настоящий TLS 1.3 Application Data (зашифрованные пользовательские данные), он отправляет специальную команду `CommandPaddingDirect` и **перестаёт паддить** — дальше поток передаётся напрямую, «разворачивая» соединение до сырого TCP.
На Linux это доходит до настоящего **zero-copy через системный вызов `splice(2)`** (функция `CopyRawConnIfExist` в `proxy/proxy.go`): данные перекидываются между сокетами прямо в ядре, без копирования в память процесса и без повторного шифрования. Отсюда почти нулевой оверхед — Xray с Vision работает даже на слабых роутерах.
> [!note] Как splice включается сейчас: машина состояний `CanSpliceCopy`
> В отличие от старого поколения, где splice был отдельным flow, в современном коде это рантайм-решение через поле `CanSpliceCopy` (отдельно для inbound и каждого outbound). У него три значения: **2** — «кандидат» (Vision-поток, ждём подтверждения), **1** — splice разрешён и активен, **3** — splice запрещён навсегда. Соединение стартует в состоянии `2`; когда Vision-reader/writer убеждается, что пошёл настоящий Application Data, состояние переводится в `1`, и следующий цикл копирования уходит в ядерный `splice`. Реальный zero-copy включается, только когда и inbound, и все outbound-ы имеют `CanSpliceCopy == 1`.
>
> Splice **запрещается** (значение `3`) в нескольких случаях, прямо прописанных в коде: соединение через мультиплексор (Mux) — Vision сознательно «ломает» такие соединения; поверх нового слоя [[xray/vless|VLESS encryption]], если под ним лежит full-random `XorConn` или не «голый» TCP-транспорт (проверка `IsRAWTransportWithoutSecurity`); а также при пустом flow. То есть сплайсить сырой поток можно, только если под Vision действительно неприкрытый TCP, а не WebSocket/gRPC/HTTP2 или полностью рандомизированное шифрование.
> [!note] Как Vision понимает, что внутри именно TLS 1.3
> Функция `XtlsFilterTls` разбирает первые пакеты по сигнатурам TLS-записей: ищет ServerHello (`16 03 03 ... 02`) и внутри него — расширение `supported_versions` со значением `03 04` (это и есть маркер TLS 1.3). Только при подтверждённом TLS 1.3 с подходящим шифром выставляется флаг `EnableXtls`, разрешающий уйти в direct copy. TLS 1.2 и слабый шифр `TLS_AES_128_CCM_8_SHA256` из этого режима исключены.
## Четыре поколения XTLS и почему остался только Vision
XTLS — оригинальная разработка проекта Xray (автор — RPRX), и именно она долго была главным козырем Xray по производительности: способ не шифровать пользовательский трафик второй раз. Но за это «прошивание» потока пришлось заплатить обнаружимостью, и механизм пережил четыре поколения. Три ранних значения flow — `xtls-rprx-origin`, `xtls-rprx-direct`, `xtls-rprx-splice` — в актуальном коде Xray-core **удалены полностью**: поиск по этим строкам по всему репозиторию не находит ничего (кроме единственной строки-ошибки про «Legacy XTLS» в загрузчике конфига). В константах flow остались только `None` и `XRV = "xtls-rprx-vision"`.
Что представляло собой каждое поколение (порядок появления — `origin` → `direct` → `splice` → `vision`):
- **`xtls-rprx-origin`** — первое поколение XTLS.
- **`xtls-rprx-direct`** — считался «теоретическим потолком производительности» XTLS, эталоном для остальных алгоритмов.
- **`xtls-rprx-splice`** — Linux-оптимизация: zero-copy пересылка внешних TLS-записей прямо в ядре через системный вызов `splice(2)`, без прохождения данных через память Xray (позже расширена и на Android).
Общая слабость всех трёх: они работали на уровне **TLS-записей** — «прорезали» или напрямую сплайсили сырые записи внешнего TLS, но **никак не маскировали характеристики вложенного (внутреннего) TLS-рукопожатия**. А именно по этому вложенному хендшейку прокси и детектируется (см. раздел «Границы Vision» ниже).
Vision решает ту же задачу принципиально иначе: добавляет **случайный паддинг во внутренний хендшейк на прикладном уровне** (обфускация длины первых пакетов) и уходит в прямое копирование только после подтверждённого TLS 1.3 Application Data. `splice` при этом никуда не делся — он стал **внутренней автоматической оптимизацией** Vision (см. раздел про механику ниже), а не отдельным пользовательским flow.
> [!warning] Не выдумка про «дыру»: почему на самом деле убрали старые режимы
> В сообществе переход иногда объясняют «была уязвимость в origin/direct». Честнее так: отдельной нумерованной уязвимости (CVE или security advisory) именно на старые flow найти не удаётся. Реальный мотив — общая проблема детекта **TLS-in-TLS**: старые режимы не скрывали вложенный хендшейк, а Vision скрывает его лучше. (Отдельная известная слабость Xray к активному зондированию — issue #625 — на самом деле относилась к реализации Shadowsocks, а не к flow-режимам XTLS.) Так что «убрали, потому что взломали» — неточно; убрали, потому что подход устарел под давлением новых методов детекта.
### Хронология (по «Grand Chronicle» Project X)
Датировка удаления старых режимов — по официальной летописи проекта и обсуждениям на GitHub:
- **3 октября 2022** — анонс нового flow (будущий Vision): решает проблемы прежних flow, включает splice для TLS 1.3 напрямую, добавляет обфускацию длины TLS-хендшейка.
- **29 октября 2022, v1.6.2** — первый релиз с Vision.
- **8 февраля 2023, v1.7.5** — **последняя** версия, где ещё присутствуют Origin/Direct/Splice. При их использовании выводится предупреждение о депрекации с советом перейти на `xtls-rprx-vision`.
- **9 марта 2023, v1.8.0** — старые flow **удалены**; Vision доработан (изменён алгоритм паддинга — версии Vision до и после несовместимы между собой) и вышел вместе с [[xray/reality|REALITY]].
Тренд продолжается: к 2025–2026 годам в Xray объявлен устаревшим уже и VLESS **вообще без flow** — его мигрируют на VLESS с Vision.
> [!warning] Совместимость конфигов
> Конфиг со старым flow (`xtls-rprx-direct` и т.п.) современный Xray-core загрузить не сможет — загрузчик отдаёт ошибку об удалённой фиче «Legacy XTLS» с советом использовать `xtls-rprx-vision with TLS or REALITY`.
## Границы Vision: честно о TLS-in-TLS
Важно не переоценивать Vision. Он маскирует **длины первых пакетов** рукопожатия, но не делает прокси невидимым. Академическая работа **USENIX Security 2024** «Fingerprinting Obfuscated Proxy Traffic with Encapsulated TLS Handshakes» (Xue, Kallitsis, Houmansadr, Ensafi) описывает протокол-агностический детектор вложенного TLS-хендшейка и **называет `xtls-rprx-vision` поимённо** как схему, которая лишь незначительно затрудняет обнаружение. Причина: детектор смотрит не только на длины отдельных пакетов, но и на размеры «всплесков» трафика (bursts), тайминги, направление и число round-trip — а паддинг первых пакетов эти признаки не убирает. Детектор развёрнут на реальном интернет-провайдере на более чем миллион пользователей; по данным работы, обфусцированные прокси в стандартной конфигурации распознаются с высокой полнотой и очень низким уровнем ложных срабатываний.
Проще говоря: Vision решает конкретную задачу — убрать характерную «сигнатуру длин» служебных пакетов прокси. Это закрывает целый класс простых детекторов, но не спасает от анализатора, который смотрит на форму трафика в целом.
На практике это подтверждается сообщениями (форум [net4people/bbs](https://github.com/net4people/bbs), 2023–2025): в России фиксируют блокировки, срабатывающие не на length-сигнатуре, а на **поведении соединения** — например «тихая заморозка» после определённого объёма данных от зарубежного IP, когда триггером служит сам факт долгого TLS 1.3-соединения к подозрительному адресу, а не размеры первых пакетов. Такой детект Vision в принципе не обходит, потому что работает на другом уровне. Подробнее о поведенческих эвристиках DPI — в [[VLESS/dpi-tls-june-2026|DPI TLS heuristics 2026]].
> [!tip] Где Vision в общем стеке
> Роли слоёв в связке принято разводить так (по обсуждениям XTLS): [[xray/reality|REALITY]] убирает почерк **серверного** TLS и прячет сервер за чужим сайтом; **Vision** убирает признак **TLS-in-TLS** (длины хендшейка); **uTLS** имитирует почерк **клиентского** TLS (например, Chrome). Ни один из слоёв не заменяет другой — каждый закрывает свой признак, и даже вместе они не дают стопроцентной невидимости.
## Ограничения Vision
- **Только TCP.** Vision работает поверх прямого TLS 1.3 или REALITY по TCP. Для UDP есть отдельный вариант `xtls-rprx-vision-udp443` (разрешает UDP 443) и механизм XUDP, но сам Vision UDP напрямую не оптимизирует — в коде для UDP-команды возвращается ошибка «xtls-rprx-vision doesn't support UDP».
- **Только TLS/REALITY напрямую.** Обернуть Vision в WebSocket, gRPC или ещё один слой шифрования нельзя — код отвечает «XTLS only supports TLS and REALITY directly for now».
- **Нужен TLS 1.3.** Если внешний слой договорился на TLS 1.2, direct copy не включится (паддинг останется, но выигрыша splice не будет).
- **Несовместим с mux.** Vision означает копирование 1-в-1 от клиентского соединения к целевому. Мультиплексор (mux) наоборот гонит несколько клиентских соединений через одно — и внутри такого объединённого потока Vision не может понять, куда какие байты относятся. Поэтому mux с Vision не работает; в mux-соединении нельзя определить, куда отправлять данные.
## 📚 См. также
- [[xray/vless|Протокол VLESS]] — протокол, в котором задаётся поле `flow`
- [[xray/reality|REALITY]] — слой безопасности, с которым Vision обычно работает в паре
- [[xray/project-x|Project X (Xray-core)]] — обзор проекта, истории XTLS и всех технологий
- [[xray/xhttp|XHTTP]] — альтернативный транспорт (там Vision не используется)
- [[VLESS/dpi-tls-june-2026|DPI TLS heuristics 2026]] — как DPI детектит связку даже с Vision
- 🔗 [proxy/proxy.go](https://github.com/XTLS/Xray-core/blob/main/proxy/proxy.go) — исходник механики Vision (TrafficState, XtlsPadding, XtlsFilterTls, CopyRawConnIfExist)
- 🔗 [Руководство VLESS TCP REALITY (discussions #3518)](https://github.com/XTLS/Xray-core/discussions/3518) — подробный разбор механики Vision «на пальцах»
- 🔗 [Project X «Grand Chronicle»](https://xtls.github.io/en/about/news.html) — официальная летопись: даты появления Vision (v1.6.2) и удаления старых flow (v1.8.0)
- 🔗 [Xue et al., «Fingerprinting Obfuscated Proxy Traffic with Encapsulated TLS Handshakes», USENIX Security 2024](https://www.usenix.org/conference/usenixsecurity24/presentation/xue-fingerprinting) — детект TLS-in-TLS, где Vision назван недостаточным
- 🔗 [net4people/bbs](https://github.com/net4people/bbs) — форум с репортами о реальных блокировках VLESS/Vision
---
> [!quote] 🤖 Эти статьи открыты — можно обучать на них ИИ
> При желании вы можете натренировать ИИ на наших статьях. Исходное форматирование и скачивание всего репозитория одним zip-архивом доступны на GitHub: [исходник этой заметки](https://github.com/youtubediscord/todo/blob/main/xray/xtls-vision.md) · [весь репозиторий](https://github.com/youtubediscord/todo/tree/main).