# Session reference — Диагностика XRay Reality 2026-07-14 ## Контекст сессии - **Сервер:** VPS vps03 (80.209.240.167), XRay Reality на портах 443 и 8443 - **Клиент:** Android, v2rayNG (версия не уточнена) - **Оператор:** мобильный, IP клиента 46.159.34.212 - **Проблема:** Яндекс.Диск якобы работает через VPN, браузер — нет - **Реальное положение дел (выяснилось позже):** Пользователь отключал VPN, когда проверял Яндекс.Диск. VPN был реально выключен. Классический самообман. ## Хронология диагностики ### Фаза 1 — Подтверждение работоспособности сервера 1. `systemctl status xray` → active ✅ 2. `ss -tlnp | grep 443/8443` → LISTEN ✅ 3. `journalctl -u xray --since ... | grep ` → видно `REALITY: invalid connection from 46.159.34.212: failed to read client hello` 4. `curl -v https://google.com` с сервера → работает ✅ (через IPv4, IPv6 недоступен) 5. `curl -v -4 https://google.com` с сервера → TLS handshake OK ✅ **Вывод:** Сервер жив, конфиг валиден, outbound freedom работает. ### Фаза 2 — Анализ логов ``` accepted udp:46.159.34.212:XXXXX:53 [direct] ← DNS проходит REALITY: invalid connection from 46.159.34.212:XXXXX: failed to read client hello ← TCP не проходит ``` **Ключевое наблюдение:** DNS-запросы (UDP:53) видны в логах как `accepted udp:...:53 [direct]`, а TCP-соединения — только как `REALITY: failed to read client hello`. Ни одного `accepted tcp:` из этого IP не было. ## Полезные наблюдения ### `curl` зависает, а не таймаутит Обычно curl на Android при недоступности пишет `curl: (28) Connection timed out after X ms`. В этой сессии curl просто висел бесконечно — не было ни ответа, ни таймаута. Это нестандартное поведение, указывающее на то, что TCP SYN достигает сервера, но дальнейшее взаимодействие обрывается. ### `REALITY: failed to read client hello` — что это значит Ошибка означает: 1. TCP трёхстороннее рукопожатие **состоялось** (SYN → SYN-ACK → ACK прошли) 2. После ACK сервер ожидает TLS ClientHello для проверки REALITY 3. Клиент отправляет что-то, что непохоже на ClientHello, или отправляет ClientHello с неверными параметрами Возможные причины (по вероятности): 1. **Клиент использует V2Ray-core вместо XRay-core** — REALITY — эксклюзив XRay. V2Ray-core не умеет REALITY, соединение приходит но TLS-рукопожатие неправильное. 2. **Неверный publicKey или shortId** — REALITY проверяет их на уровне ClientHello. 3. **Профиль v2rayNG не выбран** — телефон шлёт трафик на порт 443, но не через v2rayNG. ### Стратегия доменов IPIfNonMatch Пользователь заметил, что смена `Domain Strategy` с `ASIS` на `IPIfNonMatch` один раз помогла, но потом перестала. **IPIfNonMatch** — v2rayNG резолвит домен в IP, и только потом применяет правила маршрутизации. Если DNS на телефоне возвращает корректный IP, это может помочь обойти проблемы с DNS-перехватом. **Почему могло помочь один раз:** - DNS-кеш на телефоне был пуст, первый запрос вернул правильный IP - После кеширования — запросы пошли по старому пути ### IPv4 vs IPv6 При проверке `curl https://google.com` на сервере: - IPv6 адреса google.com резолвятся, но `connect fails: Network is unreachable` - IPv4 (`-4`) работают нормально Это значит, что на VPS нет IPv6-связности. Если клиент резолвит google.com в IPv6 и пытается идти через XRay — соединение может не установиться. ### Продолжение сессии — Обновление сервера и новая ошибка #### Фаза 3 — `proxy/vless/encoding: invalid request version` После обновления сервера с 26.3.27 до 26.7.11 (клиент: Xray-core 26.6.27) ошибка `REALITY: failed to read client hello` сменилась на: ``` rejected proxy/vless/encoding: invalid request version ``` **Значение:** REALITY-рукопожатие прошло успешно, но VLESS-протокол на клиенте использует другой формат запроса, чем сервер. **Корень:** версия Xray на сервере (26.3.27) и на клиенте (26.6.27) различаются. Между ними изменился VLESS-протокол. При этом `install-release.sh` не обновляет сервер, потому что проверяет только GitHub `latest` релиз (который всё ещё 26.3.27), а клиент (v2rayNG) имеет более новую сборку. **Как обновить сервер вручную:** ```bash # Найти последнюю версию curl -sL https://api.github.com/repos/XTLS/Xray-core/releases | grep -E '"tag_name"' | head -5 # Скачать и распаковать curl -sL -o /tmp/xray.zip "https://github.com/XTLS/Xray-core/releases/download/v26.7.11/Xray-linux-64.zip" unzip -o /tmp/xray.zip xray -d /usr/local/bin/ chmod +x /usr/local/bin/xray systemctl restart xray ``` **Важно:** `unzip` кладёт файлы рядом с xray (geoip.dat, geosite.dat). Если извлекать всё (`unzip -o` целиком) — перезаписываются актуальные geoip/geosite свежими из архива (что может быть ок, но лучше извлекать только бинарник). #### Результат После обновления сервера до 26.7.11 (новее клиента 26.6.27) ошибка `invalid request version` должна исчезнуть. Если остаётся — обновить и клиент (v2rayNG → последняя версия). ### Продолжение сессии 2026-07-15 — Порто-независимая блокировка XRay Reality на Ростелеком #### Контекст - **Провайдер:** Ростелеком (домашний WiFi) - **Клиент:** Android, v2rayNG 2.2.6 (Xray-core 26.6.27, Lib v38) - **Сервер:** XRay 26.7.11, Reality, VLESS+XTLS+Vision - **Параметры:** flow=xtls-rprx-vision, fingerprint=chrome (потом random), encryption=none #### Симптом Вечером предыдущего дня соединение работало. На следующее утро/день: - "Internet check failed" в v2rayNG - `curl` зависает без ответа (не таймаут, не connection refused) - В логах сервера: `failed to read client hello` с IP клиента #### Попробованные меры | Мера | Что изменили | Результат | |------|-------------|-----------| | Порт | 443 → 8443 → 50000 | `failed to read client hello` на всех | | dest | reddit.com → microsoft.com → discord.com | `failed to read client hello` на всех | | serverNames | reddit.com → microsoft.com → discord.com | `failed to read client hello` (сначала `server name mismatch`, после исправления — `failed to read client hello`) | | fingerprint | chrome → random | Без изменений | | Всё вместе | 50000 + discord.com + random | Без изменений | Ни одно изменение не дало ни одного успешного `accepted tcp:` в логах. Все соединения обрывались на `failed to read client hello`. #### Вывод DPI на Ростелекоме научился распознавать **ClientHello от XRay-core** независимо от: - Порта назначения (443, 8443, 50000 — все под фильтром) - SNI (reddit.com, microsoft.com, discord.com — все под фильтром) - Настройки `fingerprint` (chrome и random — одинаково под фильтром) **Эскалация:** В такой ситуации менять параметры Reality бесполезно. Нужно менять транспорт/протокол: 1. WebSocket + TLS через nginx reverse proxy 2. Trojan protocol 3. AmneziaWG 4. Shadowsocks + v2ray-plugin (WebSocket) #### Ссылка на статью Статья [Конец удобства? Почему MTProxy начал ломаться](https://habr.com/ru/articles/1018672/) (s4q, 2 апр 2026) описывает похожую ситуацию — TLS fingerprint DPI на уровне ClientHello. Хотя статья про MTProxy, механизм детекта тот же: DPI анализирует ClientHello и принимает решение до установки TLS-сессии. Разница: MTProxy использует Fake-TLS (поддельный ServerHello), Reality использует настоящий сервер. Но fingerprinter самого ClientHello может быть распознан независимо от того, что происходит после. #### Решение: WebSocket plain (без TLS) **Шаг 1 — Добавить WS inbound на сервере:** ```json { "port": 50002, "protocol": "vless", "settings": { "clients": [ { "id": "cf4d32e5-9c19-460e-a5de-f881b01dcfe1" } ], "decryption": "none" }, "streamSettings": { "network": "ws", "security": "none", "wsSettings": { "path": "/", "headers": { "Host": "discord.com" } } }, "sniffing": { "enabled": false } } ``` **Ключевые моменты:** - `security: "none"` — **нет TLS**. WS идёт через HTTP Upgrade, ClientHello не отправляется. - `flow` не указывается — для WS без TLS flow не нужен. - `sniffing: false` — для WS без TLS сниффинг не работает (нечего сниффать). - `Host: "discord.com"` в заголовках — для маскировки HTTP-запроса. **Шаг 2 — Проверить что порт слушается:** ``` ss -tlnp | grep 50002 ``` **Шаг 3 — Настроить клиент (v2rayNG):** | Поле | Значение | |------|----------| | address | IP сервера | | port | 50002 | | id | как на сервере | | flow | (пусто) | | encryption | none | | network | ws | | security | none (не TLS!) | | ws path | / | | ws Host | discord.com | **Результат:** Соединение установилось, 2ip.io показывает IP сервера (80.209.240.167). ✅ **Почему это работает:** WS без TLS не отправляет ClientHello. DPI не с чем сравнивать fingerprint. HTTP Upgrade-запрос не имеет характерных признаков прокси-трафика. VLESS шифрует содержимое внутри WS, так что конфиденциальность сохраняется. **Trade-off:** WS без TLS виден как HTTP-трафик (не TLS), поэтому не маскируется под HTTPS. Пройдёт DPI, но может быть замечен провайдером как не-TLS трафик на нестандартном порту. Для дополнительной защиты можно использовать TLS-версию WS через nginx reverse proxy. #### Выводы по сессии 1. **Самое вероятное объяснение (первоначальное):** v2rayNG на телефоне использует V2Ray-core (старый), а не XRay-core. REALITY не поддерживается старым core. Решение: обновить v2rayNG до 1.8.13+ (там встроен XRay-core). 2. **Фактическая проблема:** версионное несоответствие Xray между сервером (26.3.27) и клиентом (26.6.27). `install-release.sh` не обновляет до не-latest версий, требуется ручное обновление. 3. **Самое тривиальное объяснение:** VPN был выключен при проверке Яндекс.Диска (подтверждено пользователем). 4. **Для будущей диагностики:** Всегда проверять реальное состояние VPN на клиенте, не полагаться на слова пользователя. Лучший индикатор — логи сервера. 5. **Новый паттерн:** `proxy/vless/encoding: invalid request version` → обновить сервер Xray до версии >= клиентской.