VPN·HUB·CRACK
Протокол поднялся, а клиент его не видит: разбор подписки · VPN HUB CRACK
Протокол поднялся, а клиент его не видит: разбор подписки
Протокол есть на ноде, но клиент его не видит
Ситуация знакомая: добавили инбаунд, панель зелёная, нода подключена, а в приложении новый протокол либо не появился, либо появился, но не работает. Причин ровно пять, и они выстраиваются в цепочку. Проверять надо по порядку: каждый следующий шаг имеет смысл только если предыдущий пройден.
📖 Незнакомые слова смотрите в Словаре терминов.
Цепочка: где теряется протокол
конфиг-профиль → включён у ноды → Xray поднял порт → порт открыт наружу
→ попал в шаблон подписки → выбран клиентом (а не балансировщиком)
1. Инбаунд не включён у ноды
Добавить инбаунд в профиль недостаточно: нода поднимает только те, что явно отмечены у неё. Симптом: Xray перезапустился, в логах «up and running», но нужного порта нет.
терминал
# на ноде: смотрим, что реально слушает Xray
ss -lntup | grep -E ":(2443|2096|2097) "
Если пусто, идите в панель и включите инбаунд у самой ноды (не только в профиле).
2. Порт закрыт файрволом
Самая обидная причина: на ноде порт слушается, а снаружи его нет. В панели всё выглядит исправным, клиент молча не подключается.
терминал
# запускать с ДРУГОГО сервера, не с самой ноды
for p in 443 2443 2096; do
timeout 5 bash -c "echo > /dev/tcp/IP_НОДЫ/$p" 2>/dev/null \
&& echo "$p открыт" || echo "$p ЗАКРЫТ"
done
Лечится ufw allow 2443/tcp или, что лучше, переносом протокола за SNI-разделение на 443 (см. Эталонные схемы).
3. Транспорт назван raw, а генератор ждёт tcp
В Xray 26 транспорт tcp переименован в raw: ядро понимает оба. Но генератор подписки может понимать только tcp: инбаунд при этом работает, порт слушается, а из выдачи клиенту он молча исчезает. Ошибок нигде нет, просто протокола нет в приложении.
было → стало
"streamSettings": { "network": "raw" } // работает на ноде, но пропадает из подписки
"streamSettings": { "network": "tcp" } // безопасный вариант
Правило: на ноде транспорт может называться как угодно, а в конфиге для подписки должен быть tcp.
4. Хост не попал в шаблон подписки
Набор подключений, которые видит клиент, задаёт только секция injectHosts в шаблоне подписки. Ни маршруты, ни балансировщики, ни список outbound'ов на это не влияют: если хоста нет в injectHosts, клиент его не получит, сколько ни настраивай ноду.
Частый случай: селектор со списком конкретных хостов. Новые туда не попадают автоматически, их нужно дописывать.
injectHosts
{
"selector": { "type": "uuids", "values": ["…", "…"] },
"tagPrefix": "proxy",
"selectFrom": "ALL",
"addVirtualHostAsOutbound": true
}
Ключ addVirtualHostAsOutbound добавляет в каждую плитку её собственный хост. Без него основным подключением у всех плиток становится один и тот же: первый из списка.
5. Балансировщик перехватывает выбор
Самый неочевидный случай. Плитки в приложении называются по-разному, а подключение у всех одно и то же: одинаковый пинг, одинаковый выход в интернет.
Причина в том, что в шаблоне включён автовыбор:
routing
"balancers": [
{ "tag": "auto", "selector": ["proxy"], "strategy": { "type": "leastPing" } }
],
"rules": [ { "network": "tcp,udp", "balancerTag": "auto" } ]
Клиент отправляет трафик не в конкретный протокол, а в балансировщик, и тот берёт быстрейший из всех. Для боевого сервиса это правильно: клиент всегда на лучшей ноде. Но проверить конкретный протокол так невозможно: вы всегда меряете одну и ту же ноду.
Чтобы плитка вела строго в свой протокол, ей нужен отдельный шаблон: без balancers, с прямым правилом "outboundTag": "proxy".
⚠️ Отсюда практический вывод: «я переключил плитку, и пинг не изменился» это не глюк приложения, а автовыбор. Проверять протоколы надо на отдельном шаблоне, иначе замеры бессмысленны.
Две ошибки API, на которых легко застрять
409 Conflict при создании профиля. Теги инбаундов уникальны глобально, а не внутри профиля. Если скопируете профиль вместе с инбаундами, получите конфликт. Дополняйте существующий профиль или переименовывайте теги.
This name is reserved при обновлении шаблона. Имя Default защищено: в запросе на обновление поле с именем передавать не нужно, только содержимое шаблона.
Порядок диагностики за две минуты
- Порт слушается на ноде? →
ss -lntup - Порт открыт снаружи? → проверка с другого сервера
- Транспорт назван
tcp? → конфиг профиля - Хост есть в
injectHosts? → шаблон подписки - Плитка не перехвачена балансировщиком? →
routing.balancers - И только потом смотреть клиента
Дальше: как собрать один умный «Автовыбор» вместо десятка плиток, читайте в статье Супер-автовыбор.