Add adaptive advert flood rate limiter#2545
Conversation
4np
left a comment
There was a problem hiding this comment.
Thanks for creating this :) I understand you want to keep a minimal footprint to alleviate some of the issues we're seeing with bad actors, but I wonder if it would be better to be able to detect bad actors and penalize them by silencing them with an increasing amount of time? Sometimes people genuinely send a message split in multiple packets, which can occasionally be more than 3, whereas bad actors can still flood the mesh by sending 3 messages and then staying silent for 5 mins.
| }; | ||
|
|
||
| class AdaptiveRateLimiter { | ||
| enum { |
There was a problem hiding this comment.
Consider adding some documentation explaining the approach uses Exponentially Weighted Moving Average (EWMA). It might be good to have unit tests for this class to verify its behavior.
There was a problem hiding this comment.
unit tests
We do unit tests these days?! haha.
No, all jokes aside, that should be easy to add in this case so will definetely do.
There was a problem hiding this comment.
Tests are added.
| } | ||
|
|
||
| public: | ||
| AdaptiveRateLimiter(uint16_t secs, uint8_t burst, uint8_t floor) |
There was a problem hiding this comment.
Consider adding some in-line documentation explaining what these arguments mean.
There was a problem hiding this comment.
I added it as comments first, but later changed my mind and went with renaming the parameters to be more descriptive. What do you think? should do right?
(Idea is that comments would be visible at the code site only, but intellisense (depending on the IDE) shows the parameter names as-is)
Correct, the attack is on-going so we needed something quick and simple. 💯
I think it depends on the attack, what they seem to prefer so far is just generating random keys/names and flood-adverting those to annoy people with auto-add and generate some congestion on the mesh.
Very true, this rate limit only apply to Thanks for the review! |
…ast limit hit age
|
In the first day of testing it turned out those stats were needed badly after all to get the proper insights, i didnt see those stats-* commands before but it seemed like the perfect place for the implementation. Few hours after updating the repeater, the advert attack started once more and i noticed due to having those stats, so that works. It grows to the appropiate limit within a few hours as expected and drops in the less busy hours. So, so far so good, i will run and monitor it a bit more so i can fine-tune EWMA values and then put it on ready to review so anyone can shoot their thoughts/idea's on it. |
|
I assume not with these changes as it is not really spamming a bunch of flood messages within a certain amount of minutes. We may need another way to handle such super spammy nodes dumping garbage in many channels. Preferably automated in firmware to prevent it from distribution throughout the mesh. |
No, in this case it wont do anything for those, as those arent adverts indeed. That's a different problem i'm affraid, which is much harder to solve. Dropping an legitimate advert in a bunch of spam adverts is acceptable, dropping messages however when someone is spamming the channels... that becomes tricky/hard to sell really quickly. If it comes through a certain repeater, one could lower its duty cycle for a bit, that will put a brake on it, but also will affect legit messages. (Today we have excluded a whole city + cities around it, just to get rid of the channel spam, hopefully at some point MC has the functionality to defend it in other ways... who knows) |

Adds an adaptive rate limiter on advert forwarding so one node cannot flood the mesh with bogus or abusive adverts. Bursts are still allowed when traffic is normal; the cap tightens when someone tries to hammer fake adverts.
The limit uses a small EWMA of recent advert traffic, so it can rise a bit when there is normal activity and fall back down again after things go quiet. Floods (in the sense of spam) hit the cap fast and the rest is dropped until the next window.
Kept the behavior as small/simple as possible and on by default for happy neighbors.
get advert.ratelimitset advert.ratelimit <state>state:on|offAlso added a repeater-only stats command so we can see what the limiter is doing without guessing:
stats-advert-ratelimitThat reports the current limit, remaining budget, denied advert count, load average, limit reached count, and seconds since last limit reached.
clear statsclears the reporting counters, but does not reset the active limiter state or give a fresh advert budget.Added native unit tests for adaptive behavior, window rollover, long idle decay, timestamp wraparound, advert limiter stats counters, and clear stats behavior.
Context:
Most intentional abuse we had so far was spamming fake adverts, as it's one of the easiest things one can make. I tried to keep this as small/simple as possible, while still putting a brake on it so it doesnt flood further into the mesh.