Skip to content

Анти-абуз ​

Задача простая на словах и неприятная на практике: отличить человека, который пользуется подпиской с телефона и ноутбука, от компании, купившей одну подписку на пятерых. 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.

Если ловит лишнее ​

  1. Посмотрите, какой анализатор дал вес — он указан в карточке нарушения
  2. Мобильные операторы: проверьте буфер CGNAT и то, что сеть опознана как мобильная
  3. Поднимите минимальный скор — уведомления станут реже, но и слабые сигналы уйдут
  4. Отключите конкретный анализатор, если он не подходит вашей аудитории
  5. Белый список снимает вопросы по конкретному пользователю или адресу навсегда

Предупреждения клиенту ​

Нарушение — ещё не повод отключать доступ. Человек часто не знает, что нарушает: раздал ключ родственнику, оставил включённым торрент-клиент, переехал и заходит из двух стран за час. Отключённый без объяснений доступ возвращается к вам же обращением «у меня не работает», и на разбор уходит больше времени, чем на само нарушение.

Поэтому клиенту можно написать: из карточки нарушения, из уведомления в 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_ENABLEDtrueглавный выключатель интеграции
ABUSE_API_URLhttps://panel.example.com/api/v3адрес внешнего API панели
ABUSE_API_KEYrwa_…ключ из предыдущего шага
ABUSE_API_TIMEOUT5сколько секунд ждать ответа

Если панель и бот стоят рядом в одной docker-сети, адрес может быть внутренним: http://remnawave-web-backend:8081/api/v3. На разных серверах — публичный https.

Что появится ​

У клиента на главной — плашка с тем самым предупреждением, которое ему отправили, и кнопкой написать в поддержку. Только последнее и только пока оно актуально: ни истории, ни скоринга, ни видов нарушений клиент не видит — этих данных нет в ответе, который получает его браузер.

У оператора в карточке клиента — чип уровня рядом с именем («Замечен», «Ограничен») и вкладка «Нарушения» с историей: дата, причина, скор, принятая мера, отправляли ли предупреждение. Вкладка только читает; предупредить, заблокировать или аннулировать можно в панели и в её уведомлениях.

Если не подключено ​

Ничего не ломается. Вкладка честно скажет, что сервис не подключён, плашки не будет, остальные экраны работают как раньше. Недоступность панели или медленный ответ трактуются так же: вопросов к клиенту нет. Ошибка в эту сторону ничего не стоит, а в обратную — отказывает честному человеку и показывает ему предупреждение о нарушении, которого не было.

Уровни ​

УровеньКогдаЧто значит
cleanнарушений за окно нет либо клиент в белом спискевопросов нет
warnedнарушения есть, мер не принималистоит присмотреться
limitedпо последнему нарушению применили блокировку или ограничение скоростидоступ уже ограничен

Аннулированные нарушения не считаются: детектор ошибся, и человек тут ни при чём. Белый список перебивает всё — его ставят руками, уже зная про нарушения.

Вердикт отдаётся ручкой GET /api/v3/violations/summary?telegram_id=…; ею же может пользоваться любая своя интеграция — например, чтобы не выдавать триал ограниченным.

AGPL-3.0 с исключением для плагинов