VPN·HUB·CRACK СУПЕР-АВТОВЫБОР: балансер без обрывов + умный роутинг · VPN HUB CRACK
Все статьи
Remnawave PRO Remnawave

СУПЕР-АВТОВЫБОР: балансер без обрывов + умный роутинг

Обновлено 11 августа 2026 Проверено

СУПЕР-АВТОВЫБОР

Обычный «Автовыбор» (leastPing) у многих работает пару минут, а потом заглохает, и помогает только перезапуск приложения. Это не случайность, а понятный баг конструкции. Ниже разберём, почему так и как собрать супер-балансер: он не залипает на задушенном транспорте, сам раскидывает нагрузку и умно роутит трафик (РФ-сервисы → мимо VPN на домашний IP, YouTube без рекламы, заграница → через быстрейшую ноду). Материал основан на реальном аудите стабильности боевого сервиса.

📖 Незнакомые слова? Все термины простыми словами смотрите в Словаре терминов.

🛠️ Конструктор конфига: заполни и скопируй

Не хочешь разбираться в тегах и стратегиях вручную, заполни поля ниже, нажми «Собрать» и скопируй готовый JSON. Ниже под ним написано, что с ним сделать в Remnawave.

Через запятую, как в поле Tag у хоста. Напр.: DE, SE, NL
Пусто: без отдельного YouTube-маршрута.
leastLoad смотрит на распределение задержек и раздаёт нагрузку шире, реже «заглохает». leastPing просто берёт ноду с наименьшим пингом по мелкой пробе, именно её и душит ТСПУ. Сомневаешься, оставь leastLoad.

Почему обычный «Автовыбор» работает → заглохает

  • Балансер leastPing выбирает из пула член с минимальным пингом. В пуле обычно есть raw-TCP + Reality + Vision на :443, у него минимальный фрейминг, значит и минимальный пинг → leastPing всегда выбирает его.
  • ТСПУ (российское DPI-оборудование у операторов) по этому транспорту душит полосу (не рвёт коннект, а зажимает скорость почти в ноль).
  • observatory/burstObservatory пингует мелкий generate_204 раз в 30 с, и крошечная проба проходит даже на задушенном канале → leastPing никогда не понижает этот raw-член → «работает → заглохает».
  • Перезапуск приложения помогает, потому что новый коннект случайно садится на ещё живой транспорт.

Доказательство (замер с РФ-точки): один и тот же reality-ключ, 12 проб connect→speedtest→hold-60с. Vision-on-raw: ~4/12 удачных. gRPC: ~15/15. Отсюда: gRPC-first.

Лечение балансера

  1. Убрать raw+Vision из пула: оставить gRPC/xHTTP члены (порты 8443/2096). raw переживает блок хуже всех.
  2. leastLoad вместо/поверх leastPing: он смотрит не на мелкую пробу, а на распределение задержек (baselines), и раскидывает шире, не залипая на одном члене.
  3. Прямые EU-ноды (1 хоп), не каскад в дефолте. Замер: каскад душит upload (≈5 Мбит↑), прямая нода работает полноценно (90+↓/90+↑). Каскад держите как обход/fallback, но дефолтный пул: прямые DE/SE (gRPC+xHTTP).
  4. Блок QUIC (QUIC: быстрый транспорт поверх UDP, по сути «HTTP/3») udp:443 → block ПЕРЕД balancer-правилом. Иначе YouTube/видео залипает в туннеле (застрявший QUIC через высоколатентный канал: симптом «скачивание идёт, а видео нет»). Порт-scope (udp:443) не трогает Telegram-звонки/STUN/DNS (они не на 443).
  5. Одна плитка на тариф. Юзер видит ОДИН «Автовыбор», а не 15 плиток, меньше путаницы, балансер сам берёт быстрейшее.

Умный роутинг: сердце супер-автовыбора

Правила идут сверху вниз, первое совпадение выигрывает. Порядок критичен:

  1. bittorrent → block (abuse от хостера).
  2. Реклама/трекеры → block (приятный бонус клиенту).
  3. udp:443 (QUIC) → block (см. п.4 выше).
  4. TikTok → balancer (заграница). ВЫШЕ всех RU-правил, чтобы TikTok никогда не ушёл в direct (в РФ он замедлен/режется, нужен заграничный выход).
  5. YouTube → RU-нода (без рекламы + РФ-пиринг, см. «Каскад» про механику «YouTube без рекламы»).
  6. Сайты-проверки IP (2ip.ru/2ip.io) → RU-нода: чтобы юзер видел российский IP и не пугался «у меня VPN палится».
  7. private CIDR → direct.
  8. RU-сервисы + анти-фрод-домены → direct (домашний IP юзера): ключевое, разбор ниже.
  9. Всё остальное → balancer (заграница, leastLoad по прямым).

Анти-фрод: почему RU-сервисы идут DIRECT, а не через RU-ноду

Самый неочевидный и самый ценный приём.

  • РФ-сайты палят VPN не по своему домену, а через анти-фрод-движки на ЗАРУБЕЖНЫХ доменах: terratraf.io (Магнит), t-tech.team (Т-Банк), gravityfield.ai / diginetica.net (Дикси), appsflyer.com / onelink.me / branch.io / adjust.com (почти все мобильные аппы).
  • Если гнать их через вашу RU-ноду (маршрут по geoip назначения), зарубежный анти-фрод-домен уйдёт за границу → движок снова видит датацентровый немецкий IP → «VPN detected».
  • Решение: эти домены → direct = выход с домашнего резидентного IP юзера. Домашний IP > датацентрового IP сервера для анти-фрода. (На практике именно direct чинил Магнит/Дикси.)
  • Вывод: в direct кладите не только .ru-домены, но и зарубежные домены РФ-сервисов (анти-фрод/аналитика/атрибуция аппов).

geo-dat-free: почему НЕ использовать geosite:/geoip:

  • Правила роутинга выполняются на КЛИЕНТЕ, его файлами geosite.dat/geoip.dat.
  • У части клиентов geosite.dat урезан → ядро падает: geosite.dat отсутствует секция YOUTUBE. Volumes с geo-файлами на нодах НЕ помогают: правила-то выполняются на клиенте!
  • Поэтому в шаблоне ноль ссылок geosite/geoip, всё явными доменами/регексами/CIDR:
  • geosite:youtubeyoutube.com, googlevideo.com, ytimg.com, ggpht.com, youtubei.googleapis.com
  • geosite:category-ruregexp:\.ru$|\.su$|\.xn--p1ai$ + явные не-.ru (vk.com, userapi.com, yastatic.net, wbstatic.net, ozonusercontent.com, avito.st + анти-фрод-домены);
  • geoip:private → явные CIDR;
  • geoip:ruубрать (РФ ловится по regexp:\.ru$; цена: RU-IP-only сайты без .ru-домена уйдут в туннель, но банки/госуслуги = .ru, ловятся).

Готовый шаблон (subscription template, geo-dat-free)

Кладётся в XRAY_JSON-шаблон подписки (subscription_templates), а не в Config Profile. proxy/ruyt инжектятся по тегам хостов.

🛑 КРИТИЧНО (проверено на Remnawave 2.7.4): шаблон обязан содержать готовый каркас xray: секции dns, inbounds и непустой массив outbounds с базовыми direct(freedom)+block(blackhole). Remnawave НЕ добавляет direct/block сам, он лишь дописывает инжектируемые proxy/ruyt в уже существующий outbounds. Если outbounds в шаблоне нет, генератор падает с TypeError: template.outbounds is not iterable (в логах ядра XrayJsonGeneratorService), а клиенту уходит пустой ответ (HTTP 200, content-length: 0): «балансер рушит подписку». Именно поэтому ниже шаблон полный, а не только routing+injectHosts.

{
  "dns": { "servers": ["1.1.1.1", "1.0.0.1"], "queryStrategy": "UseIPv4" },   // только IPv4 — без зависаний на «битом» IPv6
  "inbounds": [
    { "tag": "socks", "port": 10808, "listen": "127.0.0.1", "protocol": "socks",
      "settings": { "udp": true, "auth": "noauth" },
      "sniffing": { "enabled": true, "routeOnly": false, "destOverride": ["http", "tls", "quic"] } },
    { "tag": "http", "port": 10809, "listen": "127.0.0.1", "protocol": "http",
      "settings": { "allowTransparent": false },
      "sniffing": { "enabled": true, "routeOnly": false, "destOverride": ["http", "tls", "quic"] } }
  ],
  "outbounds": [
    { "tag": "direct", "protocol": "freedom" },
    { "tag": "block",  "protocol": "blackhole" }
  ],
  "remnawave": {
    "injectHosts": [
      { "selector": { "type": "tagRegex", "pattern": "^(DE|SE)$" }, "tagPrefix": "proxy", "selectFrom": "ALL" },
      { "selector": { "type": "tagRegex", "pattern": "^RUYT$" },    "tagPrefix": "ruyt",  "selectFrom": "ALL" }
    ]
  },
  "burstObservatory": {
    "subjectSelector": ["proxy"],
    "pingConfig": { "destination": "https://www.gstatic.com/generate_204", "interval": "30s", "timeout": "3s", "sampling": 3 }
  },
  "routing": {
    "domainStrategy": "AsIs",
    "balancers": [
      {
        "tag": "AUTO",
        "selector": ["proxy"],
        "fallbackTag": "proxy",
        "strategy": { "type": "leastLoad", "settings": { "expected": 3, "baselines": ["120ms", "250ms", "500ms"] } }
      }
    ],
    "rules": [
      { "type": "field", "protocol": ["bittorrent"], "outboundTag": "block" },
      { "type": "field", "outboundTag": "block",
        "domain": ["doubleclick.net", "googlesyndication.com", "google-analytics.com", "mc.yandex.ru", "an.yandex.ru", "adfox.ru", "criteo.com", "taboola.com", "outbrain.com", "adriver.ru"] },
      { "type": "field", "network": "udp", "port": 443, "outboundTag": "block" },
      { "type": "field", "balancerTag": "AUTO",
        "domain": ["tiktok.com", "tiktokv.com", "tiktokcdn.com", "byteoversea.com", "ibyteimg.com", "ibytedtos.com", "bytedance.com", "musical.ly"] },
      { "type": "field", "outboundTag": "ruyt",
        "domain": ["youtube.com", "youtu.be", "googlevideo.com", "ytimg.com", "ggpht.com", "youtubei.googleapis.com", "youtube-nocookie.com"] },
      { "type": "field", "outboundTag": "ruyt", "domain": ["2ip.ru", "2ip.io"] },
      { "type": "field", "outboundTag": "direct", "ip": ["127.0.0.0/8", "10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"] },
      { "type": "field", "outboundTag": "direct",
        "domain": [
          "regexp:\\.ru$", "regexp:\\.su$", "regexp:\\.xn--p1ai$",
          "vk.com", "vk.me", "userapi.com", "yandex.net", "yastatic.net", "ozonusercontent.com", "wbstatic.net", "avito.st",
          "terratraf.io", "t-tech.team", "gravityfield.ai", "diginetica.net", "retailrocket.net", "flocktory.com", "mindbox.cloud",
          "appsflyer.com", "onelink.me", "branch.io", "adjust.com", "cloudpayments.ru", "qiwi.com",
          "ip-api.com", "ipify.org", "ipinfo.io"
        ] },
      { "type": "field", "network": "tcp,udp", "balancerTag": "AUTO" }
    ]
  }
}

Что поменять под себя: теги в injectHosts (^(DE|SE)$: ваши прямые EU-ноды; ^RUYT$: RU-нода под YouTube), списки доменов (рекламу/RU-сервисы дополняйте своими). direct/block уже в шаблоне (трогать не нужно).

Как читать injectHosts (частый вопрос: «а через запятую?»)

injectHosts это массив пулов [ … ]. Каждый { … } внутри задаёт один пул:

  • selector.pattern задаёт регэксп, который матчится на поле Tag хоста в панели (именно Tag хоста, а не домен и не адрес);
  • tagPrefix определяет, как назвать полученные outbound'ы: proxyproxy, proxy-2, proxy-3… (по числу совпавших хостов). Балансер ловит их по префиксу: selector: ["proxy"];
  • selectFrom: "ALL" означает: берём все хосты, совпавшие по тегу (∩ инбаунды сквода юзера).

Главное правило: запятая разделяет разные пулы, а несколько тегов в один пул задаются через | внутри ^( … )$.

  • Несколько заграничных нод в один автовыбор → расширь регэксп, а не плоди объекты: { "selector": { "type": "tagRegex", "pattern": "^(DE|SE|NL)$" }, "tagPrefix": "proxy", "selectFrom": "ALL" }
  • Отдельный пул (RU-нода под YouTube) → добавляй новым объектом через запятую:
"injectHosts": [
  { "selector": { "type": "tagRegex", "pattern": "^(DE|SE)$" }, "tagPrefix": "proxy", "selectFrom": "ALL" },
  { "selector": { "type": "tagRegex", "pattern": "^RUYT$"   }, "tagPrefix": "ruyt",  "selectFrom": "ALL" }
]

Твой ^ATCP$ = только хосты с Tag ровно ATCP. Одна такая нода: оставь как есть; если заграничных нод несколько, перечисли их теги: ^(ATCP|DE2|NL)$ (и проставь эти теги в поле Tag у каждого хоста, иначе он не попадёт в пул).

⚠️ Один нюанс с YouTube-пулом. Правило "outboundTag": "ruyt" бьёт только в первый инжектнутый outbound (ruyt). Если RU-нод под YouTube несколько (^RUYT$ совпал с двумя+), заведи для них отдельный балансер, как AUTO: { "tag": "RUYT", "selector": ["ruyt"], "strategy": { "type": "random" } } и роуть YouTube через "balancerTag": "RUYT" вместо outboundTag. Для одной RU-ноды оставляй outboundTag: "ruyt", так проще.

Проверка перед заливкой: прогоните рендер через xray -test -config <render.json> в каталоге без geo-файлов (XRAY_LOCATION_ASSET=/tmp/empty): должно быть Configuration OK и ноль ссылок geosite:/geoip:. Так ловите и «не iterable» (пустой ответ), и geo-краш на урезанном клиенте за один шаг.

⚠️ Синтаксис селектора (проверено на 2.7.4): "selector": { "type": "tagRegex", "pattern": "^TAG$" }: именно type+pattern, не { "tagRegex": "…" }. И главное: у каждого хоста в пуле должно стоять поле tag = вашему паттерну (DE/SE/RUYT). Тег пуст хоть у одного, он не попадёт в балансер; теги пусты у всех, пул пустой, балансер ни к кому не подключится. (Самая частая причина «автовыбор не работает».)

Где это живёт и главные грабли (Remnawave)

  • Балансер и роутинг живут в subscription_templates.template_json (XRAY_JSON-шаблон подписки), а не в Config Profile и не через hosts.is_hidden.
  • 🛑 Ошибка Invalid protocol in inbound "socks". Allowed values are: … vless, wireguard при сохранении = вставил не туда. Это валидатор Config Profile / инбаундов ноды: там разрешены только серверные протоколы (vless / trojan / shadowsocks / …), а socks и http из шаблона это клиентские (инбаунды для приложения юзера, не для ноды). Весь этот JSON целиком идёт ТОЛЬКО в Подписка → Шаблоны → XRAY_JSON, там инбаунды не валидируются. Config Profile для автовыбора не трогаешь вообще. (Это самая частая причина «шаблон не сохраняется / не то».)
  • ⚠️ Главный урок: пул задаётся routing.balancers[].selector (префикс ["proxy"] тянет proxy/proxy-2/…), а НЕ строками hosts. UPDATE hosts SET is_hidden убирает плитку у юзера, но НЕ убирает задушенный raw-outbound из серверного пула → правьте шаблон, а не прячьте хост.
  • injectHosts сквод-скоупный: пул selectFrom:ALL = (хосты по тегу) ∩ (инбаунды сквода юзера) − (exclusions). is_hidden-хост остаётся в пуле, но не плиткой; excluded-хост не в пуле и не плиткой.
  • «Одна плитка на тариф» делается через internal_squad_host_exclusions: у тарифа скрываете все плитки, кроме его «Автовыбора». Чтобы обход был в пуле, но не плиткой, нужны is_hidden BYPASS-хосты (а не exclude).
  • ⚠️ HWID-заглушка путает при отладке. Если включён HWID, проверка подписки curl'ом без заголовка x-hwid отдаёт болванку vless://…@0.0.0.0:1#App not supported. Это не «нет хостов» и не поломка, а HWIDNotSupported. Проверяйте с реальным x-hwid устройства (из таблицы hwid_user_devices) либо админским GET /api/subscriptions/by-short-uuid/<id>: он HWID игнорит и показывает настоящие ссылки.
  • ⚠️ Домен vs IP (sniffing). Правила по домену (2ip.ru, анти-фрод-домены) срабатывают, только если клиент снифит домен из трафика. v2rayTun на Android в дефолте не снифит → сервис на зарубежном IP уедет в туннель мимо direct/ruyt (наглядно: 2ip.ru живёт на немецком Hetzner 188.40.167.82, а не на РФ-IP, потому на Android и кажет сервер, а на iOS всё ок). Лечится на клиенте стеком gVisor (Настройки трафика). Для подстраховки на сервере ключевые чек-сервисы кладите и по IP, не только по домену: { "type": "field", "outboundTag": "ruyt", "ip": ["188.40.167.82/32"] } для 2ip.ru. IP-правило от sniffing не зависит и работает на любом клиенте.

Доставка шаблона в приложение: без неё всё впустую

Шаблон можно собрать идеально, проставить теги, а у клиента 2ip всё равно кажет сервер. Причина почти всегда одна: приложение получает не ваш XRAY_JSON, а base64-список: голые vless://… без секции routing = full-tunnel, весь трафик в туннель, ни РФ-direct, ни балансера.

  • Формат ответа Remnawave выбирает по User-Agent (subscription_settings.response_rules). Из коробки правила есть под Clash/Mihomo/Sing-box/Stash + Fallback Base64. Под последний попадают Happ, v2rayTun, v2rayNG → им уходит base64 без роутинга.
  • Фикс: добавьте правило User-Agent ~ ^(happ|v2raytun|v2rayng) → XRAY_JSON выше Fallback Base64 (Subscription settings → Response Rules). Теперь эти клиенты получают шаблон с роутингом и балансером.
  • Альтернатива: serve_json_at_base_subscription = true (json по базовому URL всем json-совместимым), но точечное правило по UA безопаснее (не заденет тех, кому реально нужен base64).
  • Happ отдельно: при JSON-подписке Happ запускает xray-core «как есть» и берёт правила только из самого JSON: поле happ_routing для json не применяется (оно для base64/uri). После включения XRAY_JSON клиенту лучше удалить и заново добавить подписку в Happ: простой «обновить» не всегда переключает закэшированный base64 → json.

Проверка

  • 2ip / спидтест → показывает РФ-IP (через ruyt), юзер не пугается «VPN палится».
  • YouTube → грузится без рекламы (РФ-IP).
  • Банк / Магнит / Дикси / аппы → открываются (через direct, домашний IP: анти-фрод не срабатывает).
  • Заграница (Google/Discord) → через быстрейшую DE/SE-ноду.
  • При обрывеleastLoad сам пересаживает; raw больше не залипает.

Связано: базовые стратегии балансеров → «Балансировщики»; список RU-direct доменов → «Маршрутизация»; механика «YouTube без рекламы» → «Каскад». Клиентский симптом «заглохает» до конца лечит in-tunnel health-probe в приложении (периодическая проба сквозь туннель → форс-реконнект при N фейлах).