Анти-абуз
Задача простая на словах и неприятная на практике: отличить человека, который пользуется подпиской с телефона и ноутбука, от компании, купившей одну подписку на пятерых. Remnawave Admin собирает подключения с нод через агента, прогоняет их через семь анализаторов и выставляет нарушению скоринг.
Анализаторы
| Анализатор | Что ищет |
|---|---|
| Временной | одновременные подключения из разных мест, частые переключения |
| Географический | «невозможные путешествия»: Москва и Владивосток с разницей в минуты |
| По ASN | подписка живёт одновременно у нескольких провайдеров |
| По профилю | поведение не похоже на одного человека — режим дня, длительность сессий |
| По устройствам | больше устройств, чем позволяет подписка |
| По HWID | одно устройство обслуживает несколько аккаунтов |
| По User-Agent | разные клиентские приложения там, где ожидается одно |
Каждый включается и выключается отдельно, а результаты складываются в общий скоринг. Уведомление уходит, когда скоринг перевалил за минимальный скор (по умолчанию 50).
Как считаются источники
Адреса одной сети в узком префиксе (/24 для IPv4, /64 для IPv6) считаются одним источником. Иначе мобильный CGNAT, выдающий каждому соединению свой адрес, выглядел бы компанией из четырёх человек — обычная ситуация для российских операторов.
Границы, где схлопывать нельзя: хостинг, датацентры и VPN. Там соседние адреса — это разные машины, и разделение подписки живёт как раз в них.
В тексте нарушения остаются обе цифры: «3 источника (7 адресов)» — иначе инцидент невозможно разбирать.
Мобильность сети определяется по имени организации из базы ASN, а не по одноразовому флагу в метаданных адреса.
Пороги
Все настраиваются в Настройки → Нарушения → Пороги.
| Настройка | Смысл | По умолчанию |
|---|---|---|
| Минимальный скор уведомления | ниже этого числа нарушение не тревожит | 50 |
| Общий предел одновременных IP | один предел для всех вместо лимита устройств юзера, к нему прибавляются буферы на смену сети и CGNAT; 0 — у каждого свой лимит из панели | 0 |
| Буфер CGNAT для мобильных | сколько лишних адресов простить мобильному подключению | 3 |
| Макс. расстояние между городами | ниже этого расстояния перемещение не подозрительно | 50 км |
| Макс. аккаунтов на один HWID | сколько разных людей могут делить устройство без срабатывания | 2 |
| Макс. подписок аккаунта на HWID | защита от абуза мультитарифа | 10 |
| Макс. активных триалов на HWID | сколько живых пробных подписок на одном устройстве | 1 |
| Макс. пробных подписок аккаунта на HWID | сколько раз один человек может взять пробную с одного устройства, считая истёкшие | 1 |
Аккаунт — это человек, а не подписка
Подписки одного человека группируются по telegram_id, а если регистрация была без Telegram — по email. Два тарифа одного пользователя не выглядят разными аккаунтами.
Шаринг сверх лимита устройств
Абсолютный порог жёсткой блокировки по одновременным подключениям одинаков для подписки на одно устройство и на десять: либо режет большие тарифы, либо слишком мягок к маленьким. Относительный — «Жёсткая блокировка: источников сверх лимита устройств» в разделе жёсткой блокировки: при значении 5 подписка с лимитом 1 блокируется с 7 одновременных источников, с лимитом 3 — с 9. Источники считаются после схлопывания пулов операторов, и они должны выйти ещё и за порог с буферами на смену сети и CGNAT. Безлимитных (лимит 0) правило не касается. По умолчанию выключено.
То же можно собрать и автоматизацией: в событии нарушения есть лимит устройств, источников сверх лимита, порог с буферами и источников сверх порога — условие «Источников сверх лимита устройств > 5» и нужная мера, с предупреждением и задержкой. Разбор порога сохраняется и в самом нарушении.
Накрутка триалов
Правило про живые пробные подписки ловит ровно то, ради чего заводят новые аккаунты: одно устройство, на нём несколько действующих триалов. Апгрейд «пробная кончилась — купил платную» под правило не попадает, два платящих человека на общем планшете тоже.
Блокируется при этом вся связка, а не только проверяемый: иначе после его бана остальные видят на устройстве один живой триал, под правило не попадают, и накрутка стоит абузеру ровно один аккаунт из N. Платные и истёкшие подписки в связку не включаются.
Какие подписки считать пробными, задаётся списком тегов и UUID внутренних сквадов — там же, в порогах.
Когда устройство отвязывают
Правила выше смотрят на живые подписки, и обойти их пробовали так: отвязать устройство со старого аккаунта, завести новый через email, привязать то же железо и взять свежую пробную. Раньше отвязка удаляла запись, и в связке всегда оставался один аккаунт — порог не брался никогда.
Теперь отвязка только помечается: устройство помнит всех, кого на нём видели. В карточке пользователя такие устройства лежат на вкладке Удалённые рядом с текущими. Возврат устройства на тот же аккаунт пометку снимает, так что переустановка приложения ничего не значит.
Обратная сторона памяти: связь через отвязанное устройство продолжает давать нарушения и после того, как с клиентом разобрались и он удалил лишние устройства. Тогда запись стирают на той же вкладке — по одной или все разом кнопкой Очистить удалённые (право «Пользователи → изменение»). Стирается только история в админке: активные устройства и панель не трогаются, а вот повторная привязка тех же устройств к другим аккаунтам больше не будет видна.
Вторая половина приёма — привязать к новой подписке свой же telegram_id. После этого обе подписки принадлежат одному аккаунту, живая пробная снова одна, и правила, считающие аккаунты, слепнут. Против этого и стоит порог пробных подписок одного аккаунта: он считает не аккаунты, а сами пробные подписки на устройстве, включая истёкшие. Конверсию «пробная → платная» он не задевает — у купившего подписка уже не помечена пробной, — как и двух разных людей с общим планшетом.
Когда устройство привязывают к аккаунту, а его уже видели на другом, уведомление приходит сразу, не дожидаясь планового скана.
Чёрный список устройств
Блокировки → HWID Blacklist: устройство помечается с действием «оповещение» или «блокировать». Совпадение ищется и при добавлении записи, и периодическим сканом.
Отдельный сторож обходит список раз в несколько минут и гасит подписки, которые ожили уже после блокировки: поднять их может что угодно — например, привязка telegram_id к подписке, заведённой через email. Записи с действием «оповещение» сторож не трогает, только сообщает о них. Отключается в Настройки → Безопасность.
Что происходит при нарушении
По скорингу подбирается рекомендация, а не приговор: наблюдать, предупредить, разобраться вручную, заблокировать временно, заблокировать. Сама панель никого не трогает — кроме одного случая: на пороге жёсткой блокировки при включённой автоблокировке (violation_auto_hard_block, по умолчанию включена) пользователь отключается сразу. Тогда в уведомлении вместо рекомендации стоит «Выполнено: пользователь заблокирован» — чтобы не гадать, случилось что-то или нет.
Отдельно настраиваются пороги жёсткой блокировки — по числу адресов, одновременных подключений, устройств, совпадений HWID и аккаунтов на устройство.
Мягкая блокировка
Между «предупредить» и «отключить совсем» есть промежуточная мера: урезать скорость. Человек остаётся на связи — сайты и мессенджеры работают, видео и торренты нет, — замечает, что интернет стал странным, и приходит разбираться. С полным отключением так не выходит: там он просто исчезает.
Ограничение вешается на адрес пользователя правилами tc на ноде. Ни конфиг Xray, ни принадлежность к сквадам это не затрагивает, поэтому мера применяется и снимается мгновенно и не задевает никого другого. Нужен агент версии 1.7.0 или новее.
Настройки → Нарушения → Ограничение скорости:
| Настройка | Смысл | По умолчанию |
|---|---|---|
| Ограничение скорости | включает механизм | включено |
| Скорость по умолчанию | сколько оставить нарушителю, кбит/с | 1024 |
| Резервный сквад для нарушителей | куда дополнительно увести; пусто — не трогать сквады | пусто |
| Урезать скорость автоматически | резать сразу по рекомендации «разобраться вручную» | выключено |
Поставить меру можно четырьмя способами: кнопкой «🐌 Урезать скорость» под уведомлением о нарушении, вручную на вкладке Блокировки → Скорость, автоматически по расходу трафика (авто-действие «throttle» в мониторе) и автоматически по скору — если включено «Урезать скорость автоматически», детектор применит меру сам на рекомендации «разобраться вручную».
Ширину канала ноды указывать не нужно: обычный трафик идёт мимо ограничителя, под ограничение попадают только адреса наказанных.
С агентом 1.9.0 режет шейпер ноды (см. ниже): лимит действует в обе стороны, на любом порту и для IPv6 тоже. Если на ноде включён и общий потолок, клиенту достаётся меньший из двух. 0 или пусто в скорости значит «без лимита»: в окне урезания это снимает персональное ограничение, а в настройках выключает кнопку в боте и автодействия.
Если задан резервный сквад, наказанный дополнительно переезжает в него, а его прежние сквады запоминаются и возвращаются при снятии.
Адреса меняются
Пользователь меняет адрес по нескольку раз в сутки, поэтому правила не ставятся раз и навсегда — они пересобираются по живым подключениям, и новый адрес накрывается в пределах минуты. Адрес, за которым виден хоть один неограниченный пользователь, пропускается: за одним адресом мобильного оператора живёт целый район, и резать его целиком значит наказать невиновных.
Уведомление приходит в Telegram с кнопками: заблокировать, разорвать соединения, внести в белый список — целиком или только по тому анализатору, который и поднял тревогу (см. кнопки под уведомлениями). Автоматические действия помечаются в записи нарушения как сделанные системой — за ними не стоит администратор, и разбирать их не нужно.
Повторные уведомления по одному и тому же пользователю придерживаются кулдауном, чтобы один инцидент не превращался в поток сообщений.
Шейпер ноды
Свой потолок скорости на каждый адрес клиента ноды — против качальщиков, без ущерба для остальных. Настраивается отдельно для каждой ноды: Сервера → Ноды панели → меню ноды → Шейпер клиентов. По умолчанию выключен.
| Поле | Смысл |
|---|---|
| Порты inbound'ов | на эти порты приходят клиенты; подставляются из профиля ноды |
| Скачивание, отдача | потолок на каждый адрес, Мбит/с; 0 — без потолка |
| Режим штрафа | кто за окно прокачал больше порога (обе стороны вместе), на время получает штрафную скорость |
Как это устроено: агент (1.9.0+) вешает на вход и выход интерфейса программу eBPF. Скачивание она придерживает до назначенного времени отправки, отдачу режет отбрасыванием сверх нормы. Время отправки выдерживает fq, поэтому агент ставит его в корень интерфейса, если там дефолтная дисциплина ядра, и убирает при выключении. Свою дисциплину, если вы её ставили, агент не трогает: скачивание тогда режется грубее, отбрасыванием, и окно об этом предупредит.
Как понять, что работает. Пока шейпер включён, на карточке ноды — и в компактном виде, и в таблице — виден бейдж «Шейпер»: зелёный — потолки стоят, жёлтый — скачивание режется грубо (в корне интерфейса чужая дисциплина), красный — не применился, причина в окне шейпера, в цвете темы — ждёт ответа агента.
Уведомления о штрафах. В режиме штрафа агент раз в минуту сообщает панели, кого оштрафовал. Панель находит пользователя по адресу и времени подключения и присылает уведомление в Telegram и в колокольчик, в тему нарушений: кто, на какой ноде, сколько прокачал и до какого времени урезан. Про одного пользователя — не чаще раза в 6 часов; по адресу, за которым пользователь не нашёлся, уведомления нет. Последние штрафы видны в окне шейпера, история хранится 30 дней.
Кому не подходит
За одним адресом мобильного оператора бывает несколько клиентов — потолок они делят на всех. На ноде за CDN все клиенты приходят с адресов CDN, поэтому включать там шейпер нельзя: получится один общий потолок на всех.
Разбор инцидента
В карточке нарушения видно: какие анализаторы сработали и с каким весом, адреса и источники, города и провайдеры, устройства. Отсюда же делаются действия и ставится отметка о разборе.
Блок «Подключения, давшие нарушение» называет сами подключения, а не только строку причины: какие адреса из каких стран были в сети одновременно, концы нереалистичного перемещения, какие адреса пришли через хостинг или VPN — со страной, оператором, узлом и временем. Ниже — адреса вокруг нарушения (±1 ч): строка на адрес с первым и последним появлением, числом подключений и узлами, вместо сотен строк ленты. В ленте событий у каждого подключения теперь видны страна и тип сети, у устройств в карточке — когда их обновляли в последний раз. Блок улик есть у нарушений, записанных после обновления: у старых разбор не сохранялся.
Решение по нарушению закрывает и его улики. Запросы подписки, которые уже были в разобранном нарушении, анализатор User-Agent больше не поднимает. Иначе старый запрос curl из истории подписки каждые полчаса рождал бы новое нарушение. Новые подозрительные запросы после разбора ловятся как обычно. Аннулирование идёт дальше: раз оператор признал срабатывание ложным, тот же User-Agent этого клиента детектор больше не считает подозрительным. С торрентами так же — см. Торренты.
Соседние инструменты: IP Lookup для проверки конкретного адреса, гео-карта подключений, вкладка «Общие HWID» со счётчиком живых триалов.
Торренты
Отдельная история — детект торрентов: тег роутинга Xray плюс разбор трафика через nDPI.
Если ловит лишнее
- Посмотрите, какой анализатор дал вес — он указан в карточке нарушения
- Мобильные операторы: проверьте буфер CGNAT и то, что сеть опознана как мобильная
- Поднимите минимальный скор — уведомления станут реже, но и слабые сигналы уйдут
- Отключите конкретный анализатор, если он не подходит вашей аудитории
- Белый список снимает вопросы по конкретному пользователю или адресу навсегда
Предупреждения клиенту
Нарушение — ещё не повод отключать доступ. Человек часто не знает, что нарушает: раздал ключ родственнику, оставил включённым торрент-клиент, переехал и заходит из двух стран за час. Отключённый без объяснений доступ возвращается к вам же обращением «у меня не работает», и на разбор уходит больше времени, чем на само нарушение.
Поэтому клиенту можно написать: из карточки нарушения, из уведомления в Telegram кнопкой «⚠️ Предупредить», либо автоматически вместе с применённой мерой.
Пошаговая настройка связки с ботом и кабинетом Bedolaga — в главе «Предупреждения через Bedolaga».
Тексты
Нарушения → вкладка «Предупреждения». Свой шаблон на каждый вид нарушения: раздавшему подписку и качающему торренты надо сказать разное. У каждого шаблона выключатель, порог скора и каналы — Telegram и Email: предупреждение уходит строго по отмеченным, хотя бы один канал остаётся всегда.
Тексты у каналов раздельные, переключатель Telegram / Email в шаблоне меняет редактор:
- Telegram — HTML в урезанной разметке Telegram:
<b>,<i>,<u>,<s>,<a href>,<code>,<pre>,<blockquote>,<tg-spoiler>; перенос строки — просто Enter. Telegram отвергает сообщение целиком из-за одного лишнего тега или голого&, поэтому редактор подсвечивает такие места на лету, а с ошибками шаблон не сохранится. Рядом — предпросмотр в виде сообщения. Этот же текст клиент видит в кабинете, уже без тегов. - Email — тема и обычный HTML письма с предпросмотром. Пусто — письмо собирается из текста Telegram: переносы строк, жирный, ссылки. Кнопка «Начать с текста Telegram» кладёт эту вёрстку в редактор, дальше её можно править.
Вид определяется анализатором, давшим наибольший вклад, — тем же, по которому строятся кнопки белого списка. Своего шаблона нет или он выключен — берётся общий; выключен и он — не пишем вовсе.
Не пишите в предупреждении, что увидел детектор
Ни стран, ни числа устройств, ни скоринга. Перечень сработавших признаков на руках у нарушителя — готовая инструкция по обходу: он просто разнесёт подключения по разным сетям и устройствам. Клиенту — факт и последствие, подробности остаются в панели.
Порог скора в шаблоне работает только для автоматической отправки вместе с мерой. Нажатие «Предупредить» отправит письмо при любом скоре: оператор видит нарушение целиком, и отказывать ему из-за слабого скора значит с ним спорить.
Отправка требует права violations:resolve — того же, что и блокировка: сообщение уходит человеку от имени сервиса и не отзывается. Повторная отправка по тому же нарушению делается только явно, случайный двойной клик клиенту не пишет.
Доставка
Telegram уходит через бота Bedolaga — от того же бота, с которым клиент и так общается. Письмо — тоже через него, а если бот его не доставил (не подключён, клиента не нашёл, у клиента в боте нет почты) — встроенным почтовым сервером панели, при настроенном домене отправки. Письмо получает любой клиент с почтой, есть у него Telegram или нет.
Исключение — неподтверждённая почта. Бот на такой адрес не пишет: его мог вписать кто угодно, и письмо о нарушении ушло бы постороннему. Панель это письмо тоже не досылает — в ней та же почта, что и в боте. Если других каналов нет, оператор видит причину «почта не подтверждена».
Каналы отчитываются раздельно: заблокировавший бота клиент всё равно получит письмо. Для включённых каналов у клиента нет контактов — предупреждение не уходит, и оператор видит почему.
Для Telegram нужен бот Bedolaga 4.16.0 или новее — в нём появилась ручка POST /users/{id}/notify внешнего API — и заполненные BEDOLAGA_API_URL с BEDOLAGA_API_TOKEN, те же, по которым работают обращения и карточки клиентов.
Сначала предупредить, мера — позже
Мягкий сценарий для видов нарушений, где детектор ошибается чаще: клиента предупреждают сразу, а мера применяется, только если за отведённое время ничего не изменилось. Собирается правилом в Автоматизациях: событие «Обнаружено нарушение» (или торрент), действие «Предупредить клиента», затем шаг «Урезать скорость» или «Заблокировать» с полем «Выполнить через N ч после срабатывания».
Отложенный шаг ждёт в базе и переживает перезапуск. Перед выполнением он заново проверяет кейс и пропускается, если:
- нарушение аннулировано или уже разобрано оператором;
- клиент в белом списке;
- мера уже стоит — отложенная блокировка на сутки иначе разблокировала бы навсегда заблокированного, а ограничение перебило бы ручное;
- клиент за это время написал в поддержку (обращения Bedolaga) — тогда решает оператор; проверку можно выключить у шага;
- клиент оплатил после срабатывания или у него уже есть платная подписка — если у шага стоят эти галочки (по умолчанию выключены). Оплату сверяем с транзакциями Bedolaga, а без неё — по статусу подписки: платная — живая и без триального тега или сквада. Другие аккаунты клиента ищем по Telegram ID, без него — по почте;
- правило выключили — это отменяет все ждущие шаги.
Если предупреждение в цепочке не дошло до клиента, отложенная мера не ставится вовсе: наказывать без объяснений — ровно то, от чего цепочка защищает. Повторное срабатывание по тому же клиенту вторую меру не ставит, пока ждёт первая. Что ждёт, что выполнилось и почему пропущено — в журнале автоматизаций.
Встроенный автоблок детектора (hard_block, например за накрутку триалов) срабатывает сразу. Чтобы и он шёл через предупреждение, выключите violation_auto_hard_block и заведите правило: «Обнаружено нарушение» с условием recommended_action = hard_block → «Предупредить клиента» → через N часов «Заблокировать» с галочкой «Заодно соучастники накрутки триалов на том же HWID». Как и встроенный автоблок, мера дойдёт до чужих подписок с живым триалом на том же устройстве — иначе связка продолжит работать; уже заблокированных, ограниченных и клиентов из белого списка она не тронет.
Тот же hard_block бывает и у шаринга, торрентов и User-Agent. Чтобы правило касалось только накрутки триалов, вместо него поставьте условие «Абуз пробных подписок» = да, а выбрать точнее поможет «Сработавшие правила жёсткой меры» — например, только повторный триал на устройстве. Это машинные признаки, они не зависят от текста причин. А галочки «Не выполнять, если клиент оплатил после срабатывания» и «…если у клиента уже есть платная подписка» не дадут заблокировать того, кто за время ожидания купил подписку: в журнале шаг будет пропущен с этой причиной.
Нарушения в кабинете Bedolaga
Кабинет умеет показывать клиенту предупреждение, а оператору — вердикт и историю нарушений. Панель остаётся источником данных, кабинет только отображает.
Схема
кабинет (браузер клиента) ──► бот (Web API) ──► панель (API v3)
ключ живёт здесьКабинет не обращается к панели напрямую: его фронт работает в браузере пользователя, и любой ключ, попавший туда, доступен клиенту. Ключ знает только сервер бота.
Подключение
1. Включите внешний API панели. Переменная веб-бэкенда:
EXTERNAL_API_ENABLED=trueБез неё /api/v3/* не отвечает. Состояние видно в Настройках → API.
2. Создайте ключ. API и Вебхуки → API-ключи → Создать, область доступа — только violations:read. Бот лишь читает вердикт и историю, права на изменения ему не нужны. Ключ показывается один раз, вида rwa_….
3. Пропишите четыре переменные боту:
| Переменная | Пример | Что делает |
|---|---|---|
ABUSE_API_ENABLED | true | главный выключатель интеграции |
ABUSE_API_URL | https://panel.example.com/api/v3 | адрес внешнего API панели |
ABUSE_API_KEY | rwa_… | ключ из предыдущего шага |
ABUSE_API_TIMEOUT | 5 | сколько секунд ждать ответа |
Если панель и бот стоят рядом в одной docker-сети, адрес может быть внутренним: http://remnawave-web-backend:8081/api/v3. На разных серверах — публичный https.
Что появится
У клиента на главной — плашка с тем самым предупреждением, которое ему отправили, и кнопкой написать в поддержку. Только последнее и только пока оно актуально: ни истории, ни скоринга, ни видов нарушений клиент не видит — этих данных нет в ответе, который получает его браузер.
У оператора в карточке клиента — чип уровня рядом с именем («Замечен», «Ограничен») и вкладка «Нарушения» с историей: дата, причина, скор, принятая мера, отправляли ли предупреждение. Вкладка только читает; предупредить, заблокировать или аннулировать можно в панели и в её уведомлениях.
Если не подключено
Ничего не ломается. Вкладка честно скажет, что сервис не подключён, плашки не будет, остальные экраны работают как раньше. Недоступность панели или медленный ответ трактуются так же: вопросов к клиенту нет. Ошибка в эту сторону ничего не стоит, а в обратную — отказывает честному человеку и показывает ему предупреждение о нарушении, которого не было.
Уровни
| Уровень | Когда | Что значит |
|---|---|---|
clean | нарушений за окно нет либо клиент в белом списке | вопросов нет |
warned | нарушения есть, мер не принимали | стоит присмотреться |
limited | по последнему нарушению применили блокировку или ограничение скорости | доступ уже ограничен |
Аннулированные нарушения не считаются: детектор ошибся, и человек тут ни при чём. Белый список перебивает всё — его ставят руками, уже зная про нарушения.
Вердикт отдаётся ручкой GET /api/v3/violations/summary?telegram_id=…; ею же может пользоваться любая своя интеграция — например, чтобы не выдавать триал ограниченным.