Почему прямой VPN отваливается под блокировками оператора
Симптом знаком любому оператору: клиент жалуется, что vpn не работает под блокировкой — на домашнем Wi-Fi туннель поднимается, а на мобильном интернете в зоне ограничений молчит. Причина при этом не в протоколе шифрования и не в клиентском приложении.
При блокировках и локальных шатдаунах мобильные операторы РФ переводят сеть в режим *белого списка*: абоненту доступны только whitelisted-ресурсы — часть CDN, госсайты, платёжные шлюзы. Всё остальное, включая произвольные IP дата-центров, куда обращается ваша нода, просто не маршрутизируется. Это не выборочная фильтрация протокола, а отсечение по адресу назначения.
Для VPN это значит, что первый хоп трафика — от клиента к ноде — физически не доходит. Reality-инбаунд на прямом IP не отвечает, TLS-handshake не завершается; Hysteria2 по UDP не находит адресата. Никакая маскировка протокола тут не спасает: пакет не доходит до сервера в принципе.
Отсюда следует главный архитектурный вывод для устойчивого VPN под блокировками: чинить нужно не шифрование, а транспорт первого хопа. Точка входа сервиса должна физически находиться на ресурсе, который уже в белом списке оператора. Всё остальное в статье — про то, как это сделать инженерно.
Whitelist привязан к подсетям /24, а не к вашему сервису
Белый список оператора — это не «домены вообще» и не «CDN как класс», а конкретные IP-диапазоны, как правило на уровне подсетей /24. Практический вывод неприятный: у одного хостера часть /24 может быть whitelisted, а соседняя /24 того же хостера — нет. Нельзя рассуждать категориями «этот провайдер белый».
По наблюдениям на реальных SIM в зоне ограничений: подсети Selectel часто оказываются whitelisted, а cloud.ru / SberCloud — часто нет. Но это *не* гарантия и не константа — статус подсетей меняется, диапазоны добавляют и убирают. Известны случаи, когда ранее рабочая подсеть (в том числе у Yandex) переставала проходить. Поэтому единственно верный подход — проверять каждую /24 отдельно и актуально, без ставки на «этот IP белый навсегда».
| Хостер | Частый статус whitelist | Замечание |
|---|---|---|
| Selectel | Часто whitelisted | Проверять конкретную /24, не хостер целиком |
| cloud.ru / SberCloud | Часто НЕ whitelisted | Ставить сюда origin рискованно |
| Yandex Cloud | Переменчиво | Часть диапазонов отваливалась — мониторить |
Методика проверки простая: держите тестовые endpoint'ы в разных /24 и регулярно гоняйте доступность с реальных мобильных SIM в зоне ограничений. Автоматизируйте это — статус подсети сегодня и через месяц может отличаться. Строить инфраструктуру VPN-сервиса на предположении о «вечно белом» IP — прямой путь к аварии в самый неподходящий момент.
Архитектура: вход за whitelisted CDN-edge
Раз попытка сделать белой собственную ноду ненадёжна (см. выше про изменчивость /24), устойчивая схема иная: не тащить ноду в белый список, а поставить перед ней слой, который уже там находится, — CDN-edge (например, Yandex CDN). Оператор видит обращение к «белому» CDN-домену, CDN принимает трафик на своём whitelisted edge и проксирует его на ваш origin — ноду.
Логическая цепочка выглядит так:
клиент → CDN edge (whitelisted /24) → origin-нода (XHTTP inbound)
Что требуется от CDN-слоя, чтобы схема работала:
- edge-подсети реально находятся в белых списках операторов (это опять же вопрос конкретных /24, а не бренда CDN);
- поддержка проксирования на произвольный origin (вашу ноду);
- корректный проброс HTTP-семантики, включая тело POST-запросов (это критично, разберём отдельно).
CDN-поддомен при такой архитектуре становится публичной точкой входа сервиса: именно он прописывается в клиентском конфиге как Address / SNI / Host, а реальный IP ноды наружу не светится.
Собирать этот слой можно самому — арендуя CDN и настраивая проксирование под свой транспорт, — либо брать whitelisted-вход как готовый сервис. Например, Clearway продаёт VPN-операторам именно «белый» вход перед их нодами (без продажи серверов), с edge-доменом *.whitechannel-x1-cdn.ru; оператор оставляет у себя ноды и панель, а на вход ставит уже настроенный whitelisted-слой. Оба пути валидны — выбор зависит от того, готова ли команда сама вести мониторинг подсетей и тюнинг транспорта.
Транспорт: почему XHTTP, а не Reality или Hysteria2
CDN-edge — это по сути HTTP(S)-прокси. Он пропускает то, что укладывается в веб-семантику, и не пропускает произвольные протоколы. Это сразу отсекает часть привычных решений.
XHTTP в режиме packet-up через CDN — рабочий подход именно потому, что укладывается в обычные HTTP-запросы: для edge это похоже на веб-трафик к «белому» ресурсу, и он проходит.
Reality и Hysteria2 напрямую под троттлингом обычно НЕ проходят. Hysteria2 работает поверх QUIC/UDP — CDN-edge такой транспорт до origin не проксирует. Reality использует собственный TLS-хендшейк, который не является валидным HTTP-обращением к edge, поэтому под режимом белого списка он не доходит. Это не значит, что Reality/Hysteria2 «плохие» — на прямом канале без ограничений они отличны; но под задачу устойчивости за CDN они не подходят.
Поэтому базовый выбор транспорта для сервиса, который должен пережить перевод оператора в белый список, — XHTTP поверх whitelisted CDN. Дальше всё внимание уходит на корректную раскладку данных запроса, потому что именно здесь ломается большинство первых попыток.
Критичный нюанс: uplink в body, а не в заголовке
Это самая частая и самая неочевидная ошибка при заведении XHTTP через CDN. XHTTP умеет размещать uplink-данные в разных частях запроса, и здесь легко выбрать нерабочий вариант.
Если положить полезную нагрузку в кастомный заголовок (например, X-Payload), CDN-edge этот заголовок до origin *не донесёт* — промежуточный edge режет или не форвардит нестандартные заголовки. В результате туннель рвётся, и в логах вы видите классическое unexpected EOF. Причём на прямом соединении (в обход CDN) та же конфигурация работает — что сбивает с толку при отладке.
Правильная раскладка для прохождения через CDN:
uplinkDataPlacement: "body"— полезные данные идут в теле запроса (обычное тело POST, которое CDN обязан пробросить на origin);- session / seq — в cookie;
- padding — в query-параметрах.
Тогда всё, что несёт нагрузку, доходит до ноды как штатное тело запроса, а служебные метаданные едут в тех местах, которые CDN сохраняет. Держать uplink в body полезно и по второй причине — экономической: крупные POST снижают число мелких запросов (об этом ниже). Запомните правило: увидели unexpected EOF на XHTTP-через-CDN — первым делом проверяйте, что uplink идёт в body, а не в заголовке.
Настройка ноды и клиента: панели, порты, совпадение path
На стороне инфраструктуры за CDN живёт обычная нода под управлением одной из панелей — Remnawave, 3x-ui, Marzban или Hiddify. Нода держит XHTTP-инбаунд на выделенном порту (например, 25454), а CDN настроен проксировать входящий трафик на origin-IP:порт.
Клиентский конфиг при этом указывает не на IP ноды, а на CDN-поддомен: он выставляется как Address / SNI / Host. И здесь второй источник «не поднимается туннель» после истории с body: path и extra на клиенте и на ноде должны совпадать точь-в-точь. Любое расхождение — лишний слэш, другой регистр, несовпадающий параметр — и туннель не встанет, часто без внятной ошибки.
Чек-лист параметров, которые обязаны совпадать по обе стороны:
path;host(CDN-поддомен);- режим размещения uplink (
body) и раскладка cookie/query; - любые дополнительные поля
extra.
Практический порядок настройки вынесен в пошаговую инструкцию ниже. Главное на этом этапе — не менять параметры транспорта в одном месте, забыв про другое: клиент и нода должны быть зеркальны.
Безопасность origin: файрвол и секрет-заголовок
Как только вы спрятали ноду за CDN, критично, чтобы origin не принимал прямые обращения мимо CDN. Иначе реальный IP ноды рано или поздно засветится (сканеры, утечка из конфига), и тогда весь смысл whitelisted-входа теряется — ноду можно заблокировать или атаковать напрямую.
Два уровня защиты, которые нужно поставить сразу:
- Файрвол на вход. На XHTTP-порт origin пускать трафик только с IP gateway/CDN-edge. Все остальные источники — drop. Это отсекает и сканеры, и прямые попытки достучаться до ноды.
- Секрет-заголовок
X-Cdn-Auth. CDN добавляет к каждому проксируемому запросу секретный заголовок, а origin проверяет его наличие и значение; запросы без корректногоX-Cdn-Authотбрасываются на уровне ноды. Это защищает даже в случае, если кто-то узнал IP, но не знает секрета.
Сочетание «файрвол по IP + секрет-заголовок» даёт эшелонированную защиту: первый уровень отсекает по адресу, второй — по знанию секрета. Для инфраструктуры VPN-сервиса это не опция, а обязательный минимум — открытый origin обесценивает всю работу по whitelisted-входу.
Экономика трафика и учёт в панели
У whitelisted-CDN схемы есть своя себестоимость, и её надо считать заранее. Номинальная цена за гигабайт мало что говорит: у провайдеров с тарификацией запросов XHTTP-профиль добавляет к счёту отдельную статью, и реальная ставка получается заметно выше прайсовой. Реальная удельная стоимость выводится только из собственного биллинга: она зависит от профиля трафика абонентов и от того, тарифицирует ли провайдер запросы. Отсюда практический рычаг: крупные POST в теле запроса (тот самый body-uplink) снижают число запросов и, соответственно, стоимость. То есть выбор в пользу body — одновременно и про надёжность, и про экономику.
На стороне учёта потребления помогает панель. В Remnawave есть множитель потребления ноды и per-user лимиты. Множитель определяет, с каким коэффициентом трафик через конкретную ноду списывается против лимита пользователя:
| Множитель ноды | Эффект |
|---|---|
| 1 | Трафик считается 1:1 против лимита юзера |
| 0 | Трафик через ноду не списывается с лимита юзера (нода при этом работает) |
Множитель 0 удобен, когда CDN-нода — это аварийный fallback на время ограничений: пользователь не должен «сгорать» по лимиту из-за вынужденного дорогого маршрута. Так вы отделяете тарифную политику от факта, что клиент временно идёт через whitelisted-вход.
Если не хочется самим держать CDN-слой, мониторить подсети и оптимизировать стоимость запросов, whitelisted-вход можно взять как сервис — например, у Clearway, где эта часть уже настроена и тарифицируется прозрачно, а оператор оставляет у себя ноды, панель и биллинг.
Границы применимости: что whitelist-CDN НЕ решает
Важно не переоценивать инструмент и не смешивать две разные задачи. «Пробить троттлинг» и «разблокировать стриминг» — это не одно и то же.
Whitelisted-CDN решает задачу *доступности*: трафик доходит до ноды даже под режимом белого списка. Но он никак не меняет *репутацию* IP, с которого нода выходит в интернет.
Сервисы вроде Kinopoisk и другого российского стриминга банят дата-центровые IP по репутации — им неважно, как трафик дошёл до вашей ноды, важно, что финальный выход идёт с адреса дата-центра. Для доступа к такому контенту нужен резидентный (residential) IP, и whitelist-CDN этого не даёт — это отдельная инженерная задача (residential-exit, отдельные каналы выхода).
Поэтому при проектировании сервиса разделяйте два слоя: устойчивость входа (пережить перевод оператора в белый список — решается whitelisted CDN + XHTTP) и репутация выхода (доступ к контенту, чувствительному к типу IP — решается резидентными адресами). Смешивать их в одном обещании клиенту — значит гарантировать то, что архитектура не покрывает.