I have a slightly self-inflicted DoS happening in some circumstances, and I'm trying to figure out if I can use iptables to help mitigate it. The short version is "How can I limit the rate of incoming connections to a server to, say no more than 2 every 5 seconds using iptables rules?". I've read questions like this and although connected, the answer there (which I've tried - see below) doesn't achieve what I'm after.
The long version is that our client/server app maintains active connections, and one of our customer's networks keeps getting disconnected, which means a large number (15+) clients get disconnected at the same time. When their network connection is restored, they all attempt to reconnect at the same time, causing a kind of DoS. The long term solution is for us to implement randomised backoff in the client reconnect code, which we're working on doing. In the meantime, and what I've tried so far is based on resources like the SF answer above. From there, I created these 2 rules:
-A INPUT -p tcp -s 18.104.22.168 --match state --state NEW --match recent --set -A INPUT -p tcp -s 22.214.171.124 --match state --state NEW --match recent --update --seconds 5 --hitcount 3 -j DROP
Note I've specified one of our own IP address for testing, so I can attempt connections from that IP and see if the connections are blocked or allowed. It kind of works, in that the first connection attempt is accepted, as is the second. But when a 3rd attempt is made within 5 seconds, it is blocked - so far so good.
The problem is that if the client continues to try to connect (as our client code currently will do), it continues to be blocked - I guess because the second --update rule updates the timestamp, and this rule effective says there must be a 5 second gap between connection attempts. But what I'm after is allowing up to 2 connections to succeed every 5 seconds, regardless of how often they try to connect. I speculated that it might be the
--update flag which was keeping the timestamp of the most recent attempt (rather than the most recent success, which is really what I want to test against). I switched to
--rcheck, but it seems to exhibit the same behaviour, which means I'm not understanding this level of iptable-fu.
So, to summarise the question, if repeated connection attempts are being made (several per second), is there an iptable rule set which will allow them in at lower rate (e.g. with a separation of on average 2.5 seconds), rather than blocking them completely after the first 2?