Skip to content

Anti-abuse ​

Easy to state, unpleasant in practice: tell apart a person using a subscription from a phone and a laptop from five people sharing one. Remnawave Admin collects connections from nodes through the agent, runs them through seven analyzers and scores the result.

Analyzers ​

AnalyzerWhat it looks for
Temporalsimultaneous connections from different places, rapid switching
Geographicimpossible travel: two cities an hour apart, minutes apart
ASNone subscription living at several providers at once
Profilebehaviour that does not look like one person: daily rhythm, session lengths
Devicesmore devices than the subscription allows
HWIDone device serving several accounts
User-Agentdifferent client applications where one is expected

Each can be turned on or off separately, and the results add up into a score. A notification is sent once the score passes the minimum score threshold, 50 by default.

How sources are counted ​

Addresses from the same network within a narrow prefix (/24 for IPv4, /64 for IPv6) count as one source. Otherwise mobile CGNAT, which hands every connection its own address, would look like a crowd of four — an ordinary situation for mobile carriers.

Where collapsing is not allowed: hosting, datacentres and VPNs. There, neighbouring addresses are different machines, and sharing lives exactly there.

Both numbers stay in the violation text — 3 sources (7 addresses) — otherwise the incident cannot be reviewed.

Whether a network is mobile is decided by the organisation name from the ASN database, not by a one-off flag on the address record.

Thresholds ​

All of them live in Settings → Violations → Thresholds.

SettingMeaningDefault
Minimum notification scorebelow this a violation stays quiet50
Shared simultaneous IP limitone limit for everyone instead of the user's device limit, network-switch and CGNAT buffers are added on top; 0 — each user's own limit from the panel0
Mobile CGNAT bufferhow many extra addresses to forgive a mobile connection3
Max distance between citiesbelow this, movement is not suspicious50 km
Max accounts per HWIDhow many different people may share a device2
Max subscriptions per account on a HWIDguards against multi-plan abuse10
Max active trials per HWIDhow many live trial subscriptions on one device1

An account is a person, not a subscription

Subscriptions of one person are grouped by telegram_id, or by email when the registration had no Telegram. Two plans of the same user do not look like two accounts.

Sharing above the device limit ​

The absolute hard-block threshold on simultaneous connections is the same for a one-device plan and a ten-device one: it either cuts large plans or is too soft on small ones. The relative one — “Hard block: sources above the device limit” in the hard block section: with a value of 5, a plan with a limit of 1 is blocked from 7 simultaneous sources, with a limit of 3 — from 9. Sources are counted after collapsing carrier pools, and they must also exceed the threshold with network-switch and CGNAT buffers. Unlimited users (limit 0) are not affected. Off by default.

The same can be built as an automation: the violation event carries the device limit, sources above the device limit, threshold with buffers and sources above the threshold — a “Sources above the device limit > 5” condition plus the action you need, with a warning and a delay. The threshold breakdown is also saved in the violation itself.

Trial farming ​

The live-trials rule catches exactly what new accounts are created for: one device carrying several active trials. The upgrade path — trial expired, paid plan bought — does not trigger it, and neither do two paying people sharing a tablet.

The whole cluster gets blocked, not just the account under review: otherwise, once it is banned, the rest see a single live trial on the device, fall below the threshold, and the farming costs the abuser exactly one account out of N. Paid and expired subscriptions are never included.

Which subscriptions count as trials is defined by a list of tags and internal squad UUIDs, in the same thresholds section.

Unlinked devices stay on record — the user card shows them on the Removed tab — so re-linking the same hardware to a new account remains visible. The flip side: such a link keeps raising violations even after the case is settled and the customer has removed the extra devices. Delete those records on the same tab, one by one or with Clear removed (the “Users → edit” permission). Only the admin's history is erased: active devices and the panel are not touched, but re-linking these devices to other accounts will no longer be visible either.

What happens on a violation ​

The score picks a recommendation, not a verdict: watch, warn, review manually, block temporarily, block. The panel itself touches nobody — with one exception: at the hard-block threshold with auto-blocking on (violation_auto_hard_block, enabled by default) the user is disabled right away. The notification then says "Done: user blocked" instead of a recommendation, so there is nothing to guess about.

Hard-block thresholds are configured separately — by number of addresses, simultaneous connections, devices, HWID matches and accounts per device.

Soft block ​

Between "warn" and "cut off entirely" there is a middle measure: throttle the speed. The person stays online — sites and messengers work, video and torrents don't — notices the internet has gone weird, and comes to sort it out. A full block gets you nothing of the sort: they simply disappear.

The limit is attached to the user's address, via tc rules on the node. It touches neither the Xray config nor squad membership, so it applies and lifts instantly and affects nobody else. Requires agent 1.7.0 or newer.

Settings → Violations → Speed throttling:

SettingMeaningDefault
Speed throttlingenables the mechanismon
Default speedwhat the violator is left with, kbit/s1024
Reserve squad for violatorswhere to move them as well; empty — leave squads aloneempty
Throttle automaticallyapply straight away on the "review manually" verdictoff

There are four ways to apply it: the "🐌 Throttle" button under a violation notification, by hand on the Blocking → Throttling tab, automatically by traffic usage ("throttle" as the monitor's auto-action), and automatically by score — with "Throttle automatically" on, the detector applies it itself on the "review manually" verdict.

The node's link width does not need to be configured: ordinary traffic bypasses the shaper entirely, only the violators' addresses go through it.

With agent 1.9.0 the node shaper does the cutting (see below): the limit applies in both directions, on any port and to IPv6 as well. If the node-wide cap is enabled too, the client gets the lower of the two. 0 or empty speed means no limit: in the throttle dialog it lifts the personal limit, in settings it turns the bot button and automatic actions off.

With a reserve squad configured, the violator is moved there as well, and their previous squads are remembered and restored when the limit is lifted.

Addresses change

People change addresses several times a day, so rules are not set once and forgotten — they are rebuilt from live connections, and a new address is covered within a minute. An address with even one non-throttled user behind it is skipped: a single mobile-carrier address serves a whole district, and throttling it wholesale would punish the innocent.

The notification arrives in Telegram with buttons: block, drop connections, whitelist — either entirely or only for the analyzer that raised the alarm (see buttons under notifications). Automatic actions are marked in the record as taken by the system — there is no administrator behind them and nothing to review.

Repeat notifications about the same user are held back by a cooldown, so a single incident does not turn into a stream of messages.

Node shaper ​

A speed cap for every client address on the node — keeps heavy downloaders in check without hurting everyone else. Configured per node: Servers → Panel nodes → node menu → Client shaper. Off by default.

FieldMeaning
Inbound portsclients connect to these ports; prefilled from the node profile
Download, uploadcap per address, Mbit/s; 0 — no cap
Penalty modewhoever moves more than the threshold within the window (both directions) gets the penalty speed for a while

How it works: the agent (1.9.0+) attaches an eBPF program to the interface ingress and egress. Download packets are held until their scheduled departure time, upload is cut by dropping what exceeds the rate. The departure time is enforced by fq, so the agent installs it at the interface root when the kernel default sits there, and removes it when the shaper is turned off. If you set your own discipline, the agent leaves it alone: download is then cut more roughly, by dropping, and the dialog warns about it.

Is it working? While the shaper is on, the node card — in the compact view and the table too — shows a “Shaper” badge: green — the caps are in place, amber — download is capped roughly (someone else's discipline sits at the interface root), red — not applied, the reason is in the shaper dialog, theme-colored — waiting for the agent.

Penalty notifications. In penalty mode the agent reports who it penalized once a minute. The panel finds the user by address and connection time and sends a notification to Telegram and the bell, in the violations topic: who, on which node, how much they moved and until when they are slowed down. At most once per 6 hours per user; an address with no matching user produces no notification. Recent penalties are listed in the shaper dialog, the history is kept for 30 days.

Where it doesn't fit

Several clients can sit behind one mobile carrier address — they share the cap. Behind a CDN every client arrives from CDN addresses, so don't enable the shaper there: everyone would share one cap.

Reviewing an incident ​

The violation card shows which analyzers fired and with what weight, the addresses and sources, cities and providers, devices. Actions and the review note are made from there.

The “Connections behind the violation” block names the connections themselves rather than a reason string: which addresses from which countries were online at the same time, both ends of an impossible trip, which addresses came through hosting or VPN — with country, provider, node and time. Below it, addresses around the violation (±1 h): one line per address with first and last appearance, number of connections and nodes, instead of hundreds of timeline rows. The event timeline now shows the country and network type of every connection, and the devices in the card show when they were last updated. The evidence block exists for violations recorded after the update: older ones did not keep the breakdown.

A decision on a violation also closes its evidence. The User-Agent analyzer no longer raises subscription requests that were part of a reviewed violation — otherwise an old curl request in the subscription history would spawn a new violation every half hour. Suspicious requests made after the review are caught as usual. Annulling goes further: once the operator calls it a false positive, the detector stops treating that same User-Agent of this customer as suspicious. Torrents follow the same rule — see Torrents.

Nearby tools: IP Lookup for a single address, the connection geo map, and the shared-HWID tab with its live-trial counter.

Torrents ​

A separate story: torrent detection, the Xray routing tag plus traffic inspection via nDPI.

If it catches too much ​

  1. Look at which analyzer contributed the weight — it is named on the violation card
  2. For mobile carriers: check the CGNAT buffer and that the network is recognised as mobile
  3. Raise the minimum score — fewer notifications, but weak signals disappear too
  4. Turn off an analyzer that does not suit your audience
  5. The whitelist settles the question for a specific user or address for good

Client warnings ​

A violation is not yet a reason to cut access. People often do not know they are breaking the rules: they shared a key with a relative, left a torrent client running, or moved and log in from two countries within an hour. Access cut without explanation comes back to you as a “my VPN is broken” ticket, and sorting it out takes longer than the violation itself.

That is why you can write to the customer: from the violation card, from the Telegram notification with the “⚠️ Warn” button, or automatically together with the applied action.

Step-by-step setup of the Bedolaga bot and cabinet side is in Warnings via Bedolaga.

Texts ​

Violations → Warnings tab. One template per violation type: someone who shares a subscription and someone who downloads torrents need different words. Every template has a switch, a score threshold and channels — Telegram and Email: the warning goes strictly through the checked ones, and at least one always stays on.

The channels have separate texts; the Telegram / Email switch in the template changes the editor:

  • Telegram — HTML in Telegram's reduced markup: <b>, <i>, <u>, <s>, <a href>, <code>, <pre>, <blockquote>, <tg-spoiler>; a line break is just Enter. Telegram rejects the whole message because of one extra tag or a bare &, so the editor highlights such places as you type, and a template with errors will not save. Next to it is a preview styled as a message. The customer sees the same text in the cabinet, without the tags.
  • Email — the subject and ordinary email HTML with a preview. Empty — the email is built from the Telegram text: line breaks, bold, links. The “Start from the Telegram text” button puts that layout into the editor so you can edit it.

The type is determined by the analyzer that contributed the most — the same one the whitelist buttons are based on. If there is no template for it or it is off, the general one is used; if that one is off too, nothing is sent.

Do not tell the customer what the detector saw

No countries, device counts or scores. A list of triggered signals in the hands of the violator is a ready-made bypass guide: they will simply spread connections across networks and devices. Give the customer the fact and the consequence; the details stay in the panel.

The score threshold in a template applies only to automatic sending together with an action. Pressing “Warn” sends the message at any score: the operator sees the whole violation, and refusing them because of a weak score means arguing with them.

Sending requires the violations:resolve permission — the same as blocking: the message goes to a person on behalf of the service and cannot be taken back. Sending again for the same violation happens only on explicit request, so an accidental double click does not write to the customer.

Delivery ​

Telegram goes through the Bedolaga bot — the same bot the customer already talks to. Email goes through it too, and if the bot did not deliver it (not connected, did not find the customer, the customer has no email in the bot), it is sent by the panel's built-in mail server, provided a sending domain is set up. Any customer with an email gets the letter, whether they have Telegram or not.

The exception is an unconfirmed email. The bot does not write to such an address: anyone could have entered it, and the violation letter would reach a stranger. The panel does not send this letter either — it holds the same email as the bot. If there are no other channels, the operator sees the reason "email not confirmed".

Channels report separately: a customer who blocked the bot still gets the email. If the customer has no contacts for the enabled channels, the warning is not sent, and the operator sees why.

Telegram requires Bedolaga bot 4.16.0 or newer — that release added the POST /users/{id}/notify external API endpoint — and BEDOLAGA_API_URL with BEDOLAGA_API_TOKEN filled in, the same ones tickets and customer cards work with.

Warn first, act later ​

A soft scenario for violation types where the detector is wrong more often: the customer is warned right away, and the action is applied only if nothing has changed within the allotted time. It is built as a rule in Automations: the “Violation detected” (or “Torrent detected”) event, the “Warn user” action, then a “Limit speed” or “Block user” step with the “Run after N h after the trigger” field.

A delayed step waits in the database and survives a restart. Before running, it re-checks the case and is skipped if:

  • the violation was annulled or already resolved by an operator;
  • the customer is whitelisted;
  • the action is already in place — otherwise a delayed one-day block would unblock someone blocked forever, and a limit would override a manual one;
  • the customer contacted support in the meantime (Bedolaga tickets or external support events) — then the operator decides; the check can be turned off for the step;
  • the customer paid after the trigger or already has a paid subscription — if these checkboxes are set on the step (off by default). Payment is checked against Bedolaga transactions, or by subscription status without it: paid means live and without a trial tag or squad. The customer's other accounts are found by Telegram ID, or by email without one;
  • the rule was turned off — this cancels all waiting steps.

If the warning in the chain did not reach the customer, the delayed action is not applied at all: punishing without explanation is exactly what the chain protects against. A repeated trigger for the same customer does not add a second action while the first one is waiting. What is waiting, what ran and why a step was skipped is in the automations log.

The detector's built-in auto-block (hard_block, e.g. for trial abuse) fires immediately. To route it through a warning too, turn off violation_auto_hard_block and create a rule: “Violation detected” with the condition recommended_action = hard_block → “Warn user” → after N hours “Block user” with the “Also trial-abuse accomplices on the same HWID” checkbox. Like the built-in auto-block, the action reaches other subscriptions with a live trial on the same device — otherwise the bundle keeps working; it does not touch customers who are already blocked, limited or whitelisted.

Sharing, torrents and User-Agent can carry the same hard_block. To make the rule about trial farming only, use the condition “Trial abuse” = yes instead, and “Triggered hard-block rules” narrows it further — for example, to a repeated trial on a device only. These are machine signals and do not depend on the wording of the reasons. The “Skip if the customer paid after the trigger” and “…already has a paid subscription” checkboxes keep the rule from blocking someone who bought a subscription while the step was waiting: the log shows the step as skipped with that reason.

Violations in the Bedolaga cabinet ​

The cabinet can show the customer a warning, and the operator the verdict and the violation history. The panel stays the source of data; the cabinet only displays it.

How it fits together ​

cabinet (customer's browser) ──► bot (Web API) ──► panel (API v3)
                                   the key lives here

The cabinet does not talk to the panel directly: its frontend runs in the user's browser, and any key that ends up there is available to the customer. Only the bot's server knows the key.

Setup ​

1. Enable the panel's external API. A web backend variable:

EXTERNAL_API_ENABLED=true

Without it /api/v3/* does not respond. The state is shown in Settings → API.

2. Create a key. API & Webhooks → API keys → Create, scope — only violations:read. The bot only reads the verdict and the history and needs no write permissions. The key is shown once and looks like rwa_….

3. Set four variables for the bot:

VariableExampleWhat it does
ABUSE_API_ENABLEDtruethe main switch of the integration
ABUSE_API_URLhttps://panel.example.com/api/v3the panel's external API address
ABUSE_API_KEYrwa_…the key from the previous step
ABUSE_API_TIMEOUT5how many seconds to wait for a response

If the panel and the bot share a docker network, the address can be internal: http://remnawave-web-backend:8081/api/v3. On different servers use public https.

What appears ​

The customer sees a banner on the home page with the very warning that was sent to them and a button to contact support. Only the latest one and only while it is relevant: the customer sees neither history nor scores nor violation types — this data is not in the response their browser gets.

The operator sees a level chip next to the name on the customer card (“Flagged”, “Limited”) and a “Violations” tab with the history: date, reason, score, the action taken, whether a warning was sent. The tab is read-only; warning, blocking or annulling is done in the panel and its notifications.

If it is not connected ​

Nothing breaks. The tab honestly says the service is not connected, there is no banner, and the other screens work as before. An unavailable panel or a slow response is treated the same way: no questions to the customer. A mistake in this direction costs nothing, while one in the other direction refuses an honest person and shows them a warning about a violation that never happened.

Levels ​

LevelWhenWhat it means
cleanno violations in the window, or the customer is whitelistedno questions
warnedthere are violations, but no action was takenworth keeping an eye on
limiteda block or a speed limit was applied for the latest violationaccess is already limited

Annulled violations are not counted: the detector was wrong, and the person has nothing to do with it. The whitelist overrides everything — it is set by hand, already knowing about the violations.

The verdict is served by GET /api/v3/violations/summary?telegram_id=…; any integration of your own can use it too — for example, to deny trials to limited customers.

AGPL-3.0 with a plugin exception