14 KiB
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 — Подтверждение работоспособности сервера
systemctl status xray→ active ✅ss -tlnp | grep 443/8443→ LISTEN ✅journalctl -u xray --since ... | grep <user-ip>→ видноREALITY: invalid connection from 46.159.34.212: failed to read client hellocurl -v https://google.comс сервера → работает ✅ (через IPv4, IPv6 недоступен)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 — что это значит
Ошибка означает:
- TCP трёхстороннее рукопожатие состоялось (SYN → SYN-ACK → ACK прошли)
- После ACK сервер ожидает TLS ClientHello для проверки REALITY
- Клиент отправляет что-то, что непохоже на ClientHello, или отправляет ClientHello с неверными параметрами
Возможные причины (по вероятности):
- Клиент использует V2Ray-core вместо XRay-core — REALITY — эксклюзив XRay. V2Ray-core не умеет REALITY, соединение приходит но TLS-рукопожатие неправильное.
- Неверный publicKey или shortId — REALITY проверяет их на уровне ClientHello.
- Профиль 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) имеет более новую сборку.
Как обновить сервер вручную:
# Найти последнюю версию
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 бесполезно. Нужно менять транспорт/протокол:
- WebSocket + TLS через nginx reverse proxy
- Trojan protocol
- AmneziaWG
- Shadowsocks + v2ray-plugin (WebSocket)
Ссылка на статью
Статья Конец удобства? Почему MTProxy начал ломаться (s4q, 2 апр 2026) описывает похожую ситуацию — TLS fingerprint DPI на уровне ClientHello. Хотя статья про MTProxy, механизм детекта тот же: DPI анализирует ClientHello и принимает решение до установки TLS-сессии. Разница: MTProxy использует Fake-TLS (поддельный ServerHello), Reality использует настоящий сервер. Но fingerprinter самого ClientHello может быть распознан независимо от того, что происходит после.
Решение: WebSocket plain (без TLS)
Шаг 1 — Добавить WS inbound на сервере:
{
"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.
Выводы по сессии
- Самое вероятное объяснение (первоначальное): v2rayNG на телефоне использует V2Ray-core (старый), а не XRay-core. REALITY не поддерживается старым core. Решение: обновить v2rayNG до 1.8.13+ (там встроен XRay-core).
- Фактическая проблема: версионное несоответствие Xray между сервером (26.3.27) и клиентом (26.6.27).
install-release.shне обновляет до не-latest версий, требуется ручное обновление. - Самое тривиальное объяснение: VPN был выключен при проверке Яндекс.Диска (подтверждено пользователем).
- Для будущей диагностики: Всегда проверять реальное состояние VPN на клиенте, не полагаться на слова пользователя. Лучший индикатор — логи сервера.
- Новый паттерн:
proxy/vless/encoding: invalid request version→ обновить сервер Xray до версии >= клиентской.