Гайд: как блокировки мая 2026 повлияли на VLESS и как адаптировать конфигурацию, чтобы он снова работал.
Контекст: разбор te-st.org «MTProxy» (№9, 02.06.2026) + технические первоисточники. Состояние на июнь 2026. Тема меняется буквально по неделям — проверяй актуальность.
Включи flow: "xtls-rprx-vision" + живой высоконагруженный донор SNI + при необходимости смени
fingerprint на firefox/qq. Это закрывает слои сигнатуры / поведения / отпечатка.
Но если сервер «заморожен» по объёму трафика или его подсеть в блоке — никакой конфиг не спасёт:
нужно менять IP/хостинг или уходить за CDN.
VLESS как протокол не «вскрыли». Поймали то, что вокруг него — три независимых слоя:
DPI смотрит не на сигнатуру, а на форму трафика: VLESS-туннель даёт «постоянный двунаправленный поток без пауз», нетипичные размеры пакетов, отсутствие реальных API-запросов к сервису-донору. Ловит VLESS+TLS+REALITY без Vision (паттерн TLS-in-TLS виден по длинам пакетов).
ТСПУ берёт подозрительные зарубежные IP из дата-центровых ASN (Hetzner, DigitalOcean, Vultr…) и подмораживает соединение после ~15–20 КБ / ~25 пакетов сервер→клиент. RST не шлют — просто таймаут. Протоколо-независимо: REALITY/Vision/маскировка не помогают. Это и есть «блокировка целыми ASN-подсетями». Конфигом не лечится.
Fingerprint Go-клиента давно в базах детекции. В мае ряду пользователей помогала смена
fingerprint с chrome на firefox/qq.
К концу мая у большинства абонентов МТС/Билайн/Мегафон/Tele2 VLESS+REALITY+Vision снова заработал — но только в правильной конфигурации и на «живом» IP.
| Симптом | Причина | Чинится конфигом? |
|---|---|---|
| Сервер недоступен (ping/SSH не идут) | IP/подсеть в блоке | ❌ менять IP/хостинг |
| Хендшейк проходит, грузит пару секунд → виснет/таймаут | TCP-заморозка по объёму или TLS-in-TLS | частично |
| Падает сразу на хендшейке | fingerprint / SNI / active probing | ✅ да |
Пингуется и SSH идёт, а VLESS виснет после короткой загрузки → работаем с конфигом. Сервер мёртв целиком → сразу к разделу про IP.
Главное — flow: "xtls-rprx-vision". Vision прокидывает внутренний TLS-record напрямую, без повторной
обёртки, и убирает сигнатуру TLS-in-TLS. Если сейчас VLESS+WS+TLS или REALITY без flow — это и есть причина.
{
"inbounds": [{
"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": "github.com:443",
"xver": 0,
"serverNames": ["github.com"],
"privateKey": "PRIVATE-KEY",
"shortIds": ["", "0123abcd"]
}
}
}],
"outbounds": [{ "protocol": "freedom" }]
}{
"outbounds": [{
"protocol": "vless",
"settings": {
"vnext": [{
"address": "IP-СЕРВЕРА",
"port": 443,
"users": [{
"id": "ВАШ-UUID",
"encryption": "none",
"flow": "xtls-rprx-vision"
}]
}]
},
"streamSettings": {
"network": "tcp",
"security": "reality",
"realitySettings": {
"serverName": "github.com",
"fingerprint": "chrome",
"publicKey": "PUBLIC-KEY",
"shortId": "0123abcd",
"spiderX": ""
}
}
}]
}Ключи: xray x25519 (выдаёт private для сервера + public для клиента).
REALITY «прикидывается» этим сайтом (serverName), а dest/target — это куда сервер
зеркалит TLS-рукопожатие при active-probing.
- Реальный высоконагруженный, «скучный», нейтральный сайт (не политика/не экзотика — такие сами под прицелом).
- TLS 1.3 + HTTP/2 (h2), валидный сертификат, ответ 200 (без редиректа 301/302).
- НЕ за Cloudflare и не за шаренным CDN, которым ты не управляешь (Cloudflare в РФ сам душат).
- Гео/ASN плаузибельны относительно сервера (хостинг донора рядом с VPS, не в другой стране).
- Не дефолтные SNI из гайдов (
google/microsoft/amazon/cloudflare— заезжены). - Избегай Apple (
apple.com/icloud.com) — несовпадение ASN выдаёт.
- Сосед-IP того же ДЦ как
dest(лучший вариант):dest=<IP-соседа>:443,serverNames=["<его cert-domain>"]. IP топологически рядом с твоим VPS — максимально правдоподобно. Это основной кейс RealiTLScanner: он сам подтверждаетtls=TLS1.3 alpn=h2для соседних IP. - Публичный домен как
dest:dest=<домен>:443. Проще, но домен резолвится в свой реальный хост (часто Cloudflare!) — обязательно вет черезdonorcheck.sh.
H=example.com
echo | openssl s_client -connect $H:443 -servername $H -tls1_3 -alpn h2 2>/dev/null \
| grep -E "Protocol|ALPN|Verify return"
curl -4 -sI -o /dev/null -w "%{http_code} h%{http_version} %{remote_ip}\n" https://$HГоден если: TLSv1.3 + ALPN protocol: h2 + Verify return code: 0 + 200 + IP не Cloudflare.
(Без -servername Cloudflare-сайты отдают «No ALPN negotiated» — тест будет неточным.)
104.16.0.0–104.31.255.255, 172.64.0.0–172.71.255.255, 188.114.96.0/20,
162.158.x, 173.245.x, 141.101.x, 131.0.72.0/22.
Скрипты — в ~/Dev/Projects/vpn/utils/RealiTLScanner/ (исходники в конце раздела):
donorcheck.sh— вет списка/лога сканера: TLS1.3 + h2 + cert + HTTP + Cloudflare, метит<< GOOD.findonor.sh— скан подсети сервера + автовет в одну команду.
# найти доноров для сервера (скан его /24 + автовет):
./findonor.sh <IP-сервера> # нужен gtimeout: brew install coreutils
./findonor.sh <IP-сервера> | grep GOOD # только победители
# или вручную в два шага (gtimeout не нужен):
./RealiTLScanner -addr <IP-сервера>/24 | tee scan.log # Ctrl-C когда хватит
./donorcheck.sh scan.log | grep GOODПравило: сканируй подсеть того сервера, который будет использовать донор. Между серверами в
разных ДЦ доноры не переиспользуются (иначе гео-мисматч). Реальный анонсируемый префикс:
whois <IP> | grep -iE 'route|cidr|netrange|inetnum'.
donorcheck.sh:
#!/usr/bin/env bash
# donorcheck.sh — auto-vet REALITY SNI/dest candidates from RealiTLScanner output.
# Per domain (resolved by hostname): TLS1.3, ALPN h2, valid cert, HTTP code, Cloudflare.
# Marks "<< GOOD" when: cert ok + h2 + HTTP 200 + NOT Cloudflare.
# ./donorcheck.sh scan.log # vet a scanner log
# ./donorcheck.sh scan.log | grep GOOD # only winners
# ./donorcheck.sh domains.txt # also accepts a plain domain list
set -u
PAR=12; TIMEOUT=8
TO=""
command -v gtimeout >/dev/null 2>&1 && TO="gtimeout $TIMEOUT"
[ -z "$TO" ] && command -v timeout >/dev/null 2>&1 && TO="timeout $TIMEOUT"
is_cf() {
echo "${1:-}" | grep -qE '^(104\.(1[6-9]|2[0-9]|3[01])|172\.(6[4-9]|7[01])|188\.114|162\.158|173\.245|141\.101|131\.0\.7[0-3])\.' \
&& echo CF || echo -
}
vet_one() {
local d="$1" out vok h2 res code ver ip cf good
out=$(printf '' | $TO openssl s_client -connect "$d:443" -servername "$d" -tls1_3 -alpn h2 2>/dev/null)
if [ -z "$out" ]; then printf '%-40s TLS1.3=NO (no TLS1.3/h2 or unreachable)\n' "$d"; return; fi
echo "$out" | grep -q 'Verify return code: 0' && vok=ok || vok=BADCERT
echo "$out" | grep -q 'ALPN protocol: h2' && h2=h2 || h2=--
res=$($TO curl -4 -sI -o /dev/null --max-time "$TIMEOUT" \
-w '%{http_code} %{http_version} %{remote_ip}' "https://$d" 2>/dev/null)
code=${res%% *}; res=${res#* }; ver=${res%% *}; ip=${res##* }
cf=$(is_cf "$ip"); good=""
[ "$vok" = ok ] && [ "$h2" = h2 ] && [ "$code" = 200 ] && [ "$cf" = - ] && good="<< GOOD"
printf '%-40s cert=%-7s alpn=%-2s http=%s/%s ip=%-15s %s %s\n' \
"$d" "$vok" "$h2" "${code:-?}" "${ver:-?}" "${ip:-?}" "$cf" "$good"
}
if [ "${1:-}" = "--one" ]; then vet_one "$2"; exit; fi
DATA=$(cat "${1:-/dev/stdin}")
cands=$(printf '%s\n' "$DATA" | grep -oE 'cert-domain=[^ "]+' | sed -E 's/cert-domain=//')
[ -z "$cands" ] && cands="$DATA"
printf '%s\n' "$cands" \
| sed -E 's/^\*\.//' \
| grep -E '^[A-Za-z0-9._-]+\.[A-Za-z]{2,}$' \
| grep -viE 'duckdns|staging|\.local$|example\.|androidapplications|game-solutions' \
| sort -u \
| xargs -P "$PAR" -I{} "$0" --one {}findonor.sh:
#!/usr/bin/env bash
# findonor.sh — find & vet REALITY donors for ANY server in ONE command.
# ./findonor.sh 203.0.113.7 # single IP -> scans its /24
# ./findonor.sh 203.0.113.0/24 # explicit CIDR
# ./findonor.sh 203.0.113.7 120 # scan 120s (default 90)
# Needs gtimeout (brew install coreutils) to bound a bare-IP scan.
set -u
HERE="$(cd "$(dirname "$0")" && pwd)"
TARGET="${1:?usage: findonor.sh <ip|cidr> [scan-seconds=90]}"
SECS="${2:-90}"
case "$TARGET" in
*/*) CIDR="$TARGET" ;;
*) CIDR="${TARGET%.*}.0/24" ;;
esac
TO=""
command -v gtimeout >/dev/null 2>&1 && TO="gtimeout ${SECS}s"
[ -z "$TO" ] && command -v timeout >/dev/null 2>&1 && TO="timeout ${SECS}s"
[ -z "$TO" ] && echo "[!] no gtimeout/timeout — pass a CIDR (not a bare IP) or it won't stop" >&2
LOG="/tmp/scan_$(echo "$CIDR" | tr -c 'A-Za-z0-9' _).log"
echo "[*] scanning $CIDR for ${SECS}s -> $LOG" >&2
$TO "$HERE/RealiTLScanner" -addr "$CIDR" 2>/dev/null | tee "$LOG"
echo "[*] vetting $(grep -c 'cert-domain' "$LOG" 2>/dev/null || echo 0) hits ..." >&2
"$HERE/donorcheck.sh" "$LOG"Если chrome не помогает, в realitySettings.fingerprint пробуй по очереди:
firefox, randomized, safari, qq. В мае возвращала доступ именно смена chrome → firefox/qq.
Меняется только на клиенте, сервер не трогать.
«Следующий шаг» против поведенческого анализа — VLESS + XHTTP + REALITY вместо TCP/Vision.
XHTTP разносит upload/download в отдельные HTTP-транзакции и добавляет паддинг → больше похоже на браузер,
можно завести за CDN. Ключевое в streamSettings:
"network": "xhttp",
"xhttpSettings": { "mode": "auto", "path": "/random-path", "xPaddingBytes": "100-1000" }Vision и XHTTP взаимоисключающие: либо TCP+Vision, либо XHTTP без flow.
Если бьёт механизм №2 (заморозка по объёму) или подсеть в блоке — конфиг бесполезен:
- Сменить хостинг/ASN на менее засвеченный (Hetzner/DO/Vultr под прицелом). Ближе к РФ и «респектабельнее» ISP — лучше.
- Завести VLESS за CDN (Cloudflare/Gcore через XHTTP/WS) — наружу торчит общий IP CDN. Учти: Cloudflare в РФ сам периодически душат.
- IPv6, если оператор его нормально маршрутизирует.
- Сплит соединений по 15–20 КБ технически обходит заморозку, но убивает скорость (50 МБ ≈ 2500 соединений) — нежизнеспособно.
Не всякий обрыв = сожжённый IP. Это два разных диагноза:
| Жёсткий блок | Флап | |
|---|---|---|
| Поведение | лежит часами/сутками, сам не оживает | пропадает на ~10 мин и возвращается сам |
| SSH / порт 22 | тоже мёртв наглухо | восстанавливается вместе со всем |
| Причина | IP/подсеть в блок-листе | эвристика ТСПУ / троттл оператора / объёмная заморозка / сам сервер |
| Лечится | только новым IP | новый IP НЕ поможет — переедешь с проблемой |
Если IP сам оживает — он НЕ в чёрном списке, менять его смысла нет.
Диагностика флапа (2 шага):
- Серверная сторона или путь из РФ? В момент провала проверь сервер не из России
(аптайм-монитор на 443 / пинг с другого зарубежного хоста):
- доступен извне, мёртв только из РФ → путь РФ→IP (DPI/оператор);
- мёртв отовсюду → сам сервер/хостер (смотри
systemctl status xray, логи 3x-ui, CPU/RAM) — IP ни при чём.
- Если путь из РФ — с чем совпадает: время суток/часы пик → троттл оператора; тяжёлая загрузка → объёмная заморозка; одновременно у всех серверов → upstream.
Вывод: меняй IP только при жёстком блоке (лежит сам по себе долго). Для флапа — failover (ниже). Звоночек: если окна растут (10 мин → часы) — вот тогда IP «догорает», пора менять.
Массовый отвал 5 июня 2026 был IP/destination- и хостинг-уровня, не конфигом: ТСПУ выборочно дропали пакеты к конкретным зарубежным IP (потеря 30–90% SYN, «флап»), плюс ложились целые хостинги (Timeweb и др.). Вывод из их же анализа: «сменой порта не лечится — нужен новый зарубежный IP». Поэтому durable-защита — не твик REALITY, а 2–3 резервных метода:
- Второй выход — другой IP / ASN / страна / протокол. Чтобы поверхность детекта отличалась, бери не второй VLESS, а другой протокол: Hysteria 2 (UDP/QUIC), Shadowsocks-2022, NaiveProxy, из экзотики — ShadowTLS v3 / TUIC v5 / Trojan+gRPC.
- Запасной IP + быстрый редеплой (снапшот/скрипт). Раз блок по destination IP — спейр-адрес и есть главный фолбэк.
- Клиент Karing + авторизация Mixed. Почти все клиенты (v2rayNG, NekoBox, Hiddify, v2RayTun, Happ…) поднимают localhost SOCKS5 на 127.0.0.1 без пароля — любое приложение узнаёт реальный exit-IP твоего сервера → IP в блок-лист → сервер сгорает быстрее. Karing закрыл: Settings → Mixed → логин/пароль. Бонус — per-app split (банки/Госуслуги/такси напрямую, через туннель только нужное).
- Авто-failover в клиенте. Собери группу url-test из 2+ узлов (основной + резерв) — клиент сам переключится при провале и вернётся, когда основной оживёт. Закрывает 10-минутные флапы без смены IP.
- Порт + fingerprint наготове (запасные порты;
fp=randomizedуже стоит) и диверсификация хостеров (Timeweb лёг целиком — не держи всё на одном).
(по разборам массового отвала, Ilya Rublev / Boosty)
- WARP в 3x-ui — это egress (как сервер выходит в интернет), а твой блок на ingress (RU-клиент → твой IP). Флапы он не лечит. Включай WARP только если отдельные сайты блокируют IP твоего VPS на своей стороне (ChatGPT, Google-капчи, стриминги).
- WARP ≠ Cloudflare CDN-фронтинг. Фронтинг (домен с оранжевым облаком + WS/XHTTP) меняет вход, но ломает REALITY (Cloudflare сам терминирует TLS), требует домен и сам душится в РФ.
- Не уводи REALITY с порта 443. Фраза «VLESS на стандартных портах уже не вариант» — про голый VLESS без REALITY. Для REALITY 443 правильный (маскировка под HTTPS).
- «Russian Trusted Root / расшифровка по ключам» — про сайты на российском хостинге. Твой зарубежный REALITY так не вскрывается: он не использует CA-сертификат, который РКН мог бы перехватить.
- Одинаковая версия Xray на клиенте и сервере (Vision/XHTTP несовместимы между версиями).
muxвыключить при использовании Vision.- Порт 443, TCP.
- Держать Xray-core свежим — улучшения Vision/XHTTP выходят часто.
- net4people/bbs #490 — новый метод TCP-блокировки по объёму
- Habr: как ТСПУ ловит VLESS в 2026 и почему XHTTP — следующий шаг
- techora: РКН заблокировал VLESS в Сибири и Москве (25.05.2026)
- digirpt: VLESS заблокировали — что делать в 2026
- Xeovo Hub: Russia widespread VLESS outages — TLS/transport hardening
- digital-report: массовая блокировка VPN-серверов с помощью ИИ
- te-st.org: разбор MTProxy (№9, 02.06.2026)
- Ilya Rublev (Boosty, закрытый канал) — разборы массового отвала 5 июня, уязвимость localhost-SOCKS5 / Karing, обзор резервных протоколов