How limit connection to multiple IPs

Hi, I’m finding for a solution to limit a subnet connections to a single IP.
To clarify, there is a client in a subnet (I call it X) that opens a lot of connections to a single IP but I don’t know that destination IP because every time is different, and I don’t want to limit total connections that the host X can open but only when it try to open a lot of connections (for example 10) to a single IP address.

This is long - I give my response as a discussion so that you understand my suggestions. Just plugging rules into a firewall can have varying results depending on what’s already there to begin with. I’ve tried to design this to not impact anything else in your firewall rules. However, I do have a warning at the end, so be sure to read it before implementing something like this.

Here goes…

If X is a static IP in that subnet, your job is easier and you don’t expose too many users to this rule.
If X is a dynamic IP in a specific subnet, then other users in that subnet get subjected to this as well…

I would create a new chain in filter table that rate-limits per src+destination IP combo, and drops subsequent new connections to the destination host for a while if the rate-limit is exceeded.

Doing this in a new chain lets the checks and actions become independent of each other. You can make one rule to limit the scope of “suspicious” new connections, and send them to the “actions” chain. It’s also more efficient since if the action list is longer than 1 or 2 rules, you don’t have to put the same matching criteria on all of them, and if you change the match criteria, you don’t have to go fix it on a long list of rules.

Add The following 4 Filter Rules as follows:
Chain = Limit-X (A new chain. You’ll have to type it manually for the first rule. You can select it afterwards)
1: Advanced->Dst Address List: “Throttled” / Action = drop (if the destination IP is in the ‘Throttled’ list, stop here)
2: Extra->Dst.Limit (rate/burst/etc as appropriate - will discuss below) / Action = Accept
3: (no match criteria) / Action = add dst to address list, address list = “Throttled”, timeout = (appropriate amount)
4: (no match criteria) / Action = drop (let this packet be the first to receive the middle finger from your router)

Add one rule to the standard “forward” chain with these options:
(if you have a rule that allows established/related packets, add this rule AFTER that)
Src. Address = (either a.b.c.X if X is a static host, or a.b.X.0/24 if X is a subnet where the offending host lives)
In. Interface = interface pointing towards X
Protocol = (tcp|udp) - optional, but helps narrow it down if the target traffic is always of a specific protocol
Src/Dst Port - same considerations as Protocol. The more specific you can make your suspicion criteria, the better. If the src/dst ports are random, then you cannot use these match criteria.
Connection State: New (you can leave this off if the rule is after something which deals with established and related connections)
Action = Jump Jump Target = Limit-X


Rate Limits

The rates on rule 2 of Limit-X specify the maximum rate at which new connections can be made.
You’ll want to set Limit By to “src. and dst. address” - this is how the random IP address gets detected, and avoids ‘popular’ destinations like Google from getting matched by several sources at once.

I don’t know how many connections you’re seeing from X, but hopefully it’s a lot, and they’re opening quickly. This narrows down how likely the rule is to catch “False positives” If it’s a sudden burst of lots of connections (dozens?) then something like 20 connections per second and a short Expire value (45 seconds) will do. Basically, once the Mikrotik starts tracking a src/dst pair, it stays in a hash. After “expire” time goes by, if no packets match that src/dst, then its entry is removed from the hash. If at any time the pair is in the hash, the number of new connections exceeds the rate described above, then the rule will no longer match, causing the connection attempt to add the destination IP into the Throttle list (rule 3). The Throttle list entry can last a lot longer if you need it to - suppose X makes several bursts of connections over several hours. As long as the dst is in Throttle, no new connections to it will go out.

Try using a log target while fine-tuning your timers, and watch things closely. Make sure your rule isn’t blocking legitimate traffic.
If you want to make a “test” version of this, change the action on rule 1 to be “Return” - this way, your firewall will not act any different than it did before, but you can see hosts getting “flagged” by watching the Throttle address list shrink and grow.

What this new chain basically does:
If it’s a new connection, and is FROM the X network (or better, the host itself), jump to Limit-X chain, else continue as normal
1 → If it’s to a host we’ve already identified as a target, then just drop the packet and stop here.
2 → If the connection rate is below the threshold, then accept the connection and stop here.
3 → Apparently, we’ve exceeded the rate, so add the destination to the Throttled list for a while
4 → Oh, and let this be the first packet we now drop as “too many connections from X to Dst.”

Note that nothing refreshes the timer on Throttle. It’s essentially putting DST into a timeout.

WARNING - Automatic blacklists can be abused to create a denial of service. If X figures out that it is being filtered, it can start sending bursts of connections to important hosts (dns servers, google’s main IP addresses, your website, etc. - so be sure to be as specific as possible in your match criteria rule in the forward chain! You could white-list some services/dst IP addresses by matching them between rules 1 and 2 above, with the action of RETURN (not Accept)