VPN·HUB·CRACK
Абуз подписок: вытянули конфиг и раздали · VPN HUB CRACK
Абуз подписок: вытянули конфиг и раздали
Абуз подписок: вытянули конфиг и раздали
Один человек купил подписку, а пользуются ей пятеро. Или скрипт вытянул ваш конфиг и раздал его в чужом сервисе. Оба случая — про одно: подписка это ссылка, а ссылку можно прочитать.
Статья о том, как это делают, и — что важнее — почему привычные защиты от этого не спасают, а какие меры действительно работают. Готового скрипта обхода тут не будет: ваша задача закрыть дыру, а не воспроизвести её.
Как вытягивают
Подписка отдаётся по HTTP. Приложение забирает её обычным запросом, и всё, что делает приложение, повторит скрипт. Он подставляет те же заголовки, что шлёт настоящий Happ или sing-box: User-Agent: Happ/3.13.0, придуманный X-Hwid, X-Device-Model, иногда подставные X-Real-Ip и X-Forwarded-For. Сервер видит «приложение» и отдаёт настоящий конфиг — реальные адреса нод и ключи. Дальше конфиг уходит в любой клиент или чужой сервис.
Корень в одной фразе: заголовок — это то, что клиент говорит о себе, а не факт. Всё, что клиент рассказывает про своё приложение и устройство, подделывается за пять минут.
Три защиты, которые не работают
С них надо начать, потому что на них чаще всего надеются, и зря.
Проверка User-Agent
Идея: отдавать конфиг только при правильном User-Agent приложения. Проблема: User-Agent — обычная строка запроса, её ставит клиент. Скрипт из этой схемы просто пишет туда Happ/3.13.0 и проходит. Это не защита, а вежливая просьба, которую абузер не обязан выполнять.
Лимит устройств (HWID)
hwidDeviceLimit в Remnawave считается главным рычагом против шеринга. На деле это счётчик, а не замок. Заголовок x-hwid — произвольная строка, которую клиент придумывает сам; сервер не проверяет её происхождение. Мы это проверяли на живом сервере: curl с любым x-hwid регистрирует новое устройство и занимает слот лимита. Сгенерировал новый HWID — получил новый слот.
Отсюда точная граница того, что HWID-лимит умеет: он ограничивает массовое одновременное расшаривание — когда десять человек с одной ссылкой упираются в лимит. Он не останавливает единичную кражу и не мешает абузеру крутить слоты подделкой заголовка. Ставить его надо, но как ограничитель масштаба, не как защиту.
Шифрование ссылки Happ (crypt5)
У Happ есть шифрованные ссылки — актуальная версия crypt5 (прежний crypt4 устарел). Их часто предлагают как защиту от вытягивания. Это недоразумение, и важное.
crypt5 шифрует саму ссылку подписки, а не ответ сервера. Его настоящая цель — чтобы пользователь Happ не мог открыть свою ссылку глазами, скопировать и раздать. Против скрипта он бесполезен по двум причинам:
- Скрипт дёргает сам эндпоинт подписки напрямую, а тот по-прежнему отдаёт открытый конфиг. Зашифрованную ссылку он вообще не трогает.
- Даже если бы ответ шифровался: приватные ключи Happ зашиты в самом приложении, доступном всем, и уже вытащены реверсом в нескольких открытых проектах. «Расшифровать может только официальный клиент» — маркетинг. Расшифровывает кто угодно, без приложения.
Шифрованная ссылка полезна — от того, что пользователь раздаст свою ссылку глазами. Но это другая угроза, не вытягивание.
Что действительно защищает
Релей: спрятать выходной IP за точкой входа
Это главное, и это отвечает на вопрос «как сделать, чтобы вытянувший конфиг не получил настоящие адреса». Ответ не в шифровании, а в архитектуре: в конфиге, который уходит клиенту, стоит адрес релея или входа, а не выходной ноды.
Тогда даже вытащив конфиг целиком, атакующий получает адрес РФ-входа или CDN — то, что и так на виду, — а настоящий выходной IP за ним не видно. Reality сюда не поможет: он прячет ноду от наблюдателя в сети, но держателю конфига честно отдаёт address и port. Спрятать выход от того, кто держит конфиг в руках, умеет только промежуточный слой. Как он устроен, разобрано в «Каскаде».
Побочный выигрыш: заблокировали засвеченный адрес — меняете вход, выходная нода цела.
Response Rules: резать нестандартные запросы
Remnawave умеет отвечать по-разному в зависимости от заголовков запроса — Subscription Response Rules. Правилами можно отдавать 404, 451 или рвать соединение тем, чей User-Agent не похож на приложение: curl, python, php, пустой UA.
User-Agent CONTAINS "curl" OR CONTAINS "python" OR CONTAINS "Go-http" → STATUS_CODE_404
Честная граница: это режет наивных ботов, которые не потрудились сменить UA. Кто подставил Happ/3.13.0 — а это и делает рабочий скрипт — пройдёт. Ставить стоит: наивных большинство. Но защитой от подготовленного считать нельзя.
Ротация ссылки
Единственная мера, которая бьёт по факту утечки больно: у Remnawave есть revoke подписки. Старая ссылка умирает, вместе с ней — все раздачи с неё. Клиенту приходит новая.
Это реакция, а не профилактика: сначала надо заметить утечку. Но заметив — вы обрубаете доступ одним действием, и абузеру приходится начинать заново.
Отдавать подписку без структуры хостов
В настройках подписки можно запретить просмотр хостов и отдавать готовую happ:// ссылку, где всё уже прописано. Плюс crypt5 — от того, что пользователь раздаст ссылку глазами. Это не закрывает вытягивание эндпоинта, но снимает самый ленивый способ шеринга: «дал другу свою ссылку». Как настроить, разобрано в «Оформлении Happ/INCY».
Про идею отдавать поддельные конфиги
Замысел: тому, кто вытягивает, отдавать фейковые адреса, чтобы он не получил рабочие. Технически это те же Response Rules — по User-Agent вернуть один ответ приложению и другой всем остальным.
Честно: кто подделал UA под Happ/3.13.0, получит настоящий конфиг вместе с приложением — отличить их по заголовку нельзя, в этом вся суть проблемы. Honeypot отсечёт тех, кто поленился сменить UA, и заставит остальных чуть постараться. Как дополнительный слой поверх остального — да. Как защита — нет: он ломается ровно там же, где проверка User-Agent.
Заголовки IP: отдельная ловушка
В скрипте вытягивания часто подставляют X-Real-Ip и X-Forwarded-For. Это не про кражу конфига, а про подмену вашего представления о том, откуда пришёл запрос, и последствия у неё шире.
Если фронт использует $proxy_add_x_forwarded_for, он дописывает настоящий адрес в конец цепочки, а первым остаётся то, что прислал клиент. Любой код, который берёт «первый IP из XFF», получает подделку: антибрут по IP, бан-листы, гео-логика — всё это обманывается одним заголовком.
Правильно: доверять X-Real-IP, который фронт ставит сам из реального адреса соединения, а из X-Forwarded-For при необходимости брать последний элемент, а не первый. Клиент дописать последний элемент не может — его ставит ваш nginx.
# в приложении: источник IP — X-Real-IP (его ставит фронт, клиент не перепишет),
# запасной путь — ПОСЛЕДНИЙ элемент X-Forwarded-For, никогда не первый
Это ровно та правка, которую мы делали у себя после аудита: старый код брал первый элемент XFF, и этим обходился антибрут логина.
Чем это НЕ является
Чтобы не поставить защиту, которой нет:
- Обязательный HWID — не защита, а учёт. Слот крутится подделкой заголовка.
- Шифрование ссылки — от расшаривания глазами, не от вытягивания эндпоинта.
- Гейт по User-Agent — от наивных ботов, обходится одной строкой.
- Reality на ноде — прячет ноду от сети, но не от держателя конфига.
Что реально снижает абуз, по силе
| Мера | Что закрывает |
|---|---|
| Релей/каскад вместо адреса выхода | вытянутый конфиг не выдаёт настоящий выходной IP |
| Ротация ссылки (revoke) | обрывает доступ по утёкшей ссылке одним действием |
| HWID-лимит | ограничивает массовое одновременное расшаривание |
| Response Rules по UA | режет наивных ботов |
| Правильная обработка XFF | закрывает подмену IP в антибруте и банах |
Первые две — настоящие рычаги. Остальное — слои, которые снижают шум, но по отдельности дырявы. Смотрите ещё «Антифрод и антиабуз» про деньги и триалы и «Безопасность сервиса» про ноды и подписки целиком.