Using "recent" match option in iptables we can match recent connections, and perform simple throttling operation on incoming connections i.e. we can create simple firewall rules which will deny access from remote clients who attempt to connect "too many" times.
"recent" dynamically creates a list of IP addresses and then match against that list. The functionality of "recent" match option is simple, a list of IP addresses are created dynamically, which can be used in the future to test connection attempts against.
rate limiting is conceptually different from bandwidth throttling/limiting; a bandwidth-throttled connection will queue packets and limit the rate at which they are transmitted/received. Rate limiting will not do this; when you use rate limiting on, for example, incoming TCP connection attempts to your identd, and connections exceeding the specified limit will be denied; there is no queueing of packets.
NOTE: CONFIG_IP_NF_MATCH_RECENT flag should be enabled in Linux Kernel to use "recent" option.
Following 2 rules will limit incoming connections to destination port 22 not more than 3 in a minute and more than that will be dropped:
iptables -I INPUT -p tcp --dport 22 -m state --state NEW \
-m recent --set
iptables -I INPUT -p tcp --dport 22 -m state --state NEW \
-m recent --update --seconds 60 --hitcount 3 -j DROP
"--state NEW" – To make sure that only new connections are managed."--set" flag will make sure that the IP address of the host which initiated the connection will be added to the "recent list", where it can be tested and used again in the future i.e. in our second rule.
The second rule is where the actual magic happens.
"—update" flag tests whether the source IP address is in the list of recent connections, in our case each new tcp connection to destination port 22 will be in the list because we used the "--set" flag to add it in the preceeding rule.
"--seconds" flag is used to make sure that the source IP address is only going to match if the last connection was within the timeframe given.
"--hitcount" flag matches only if the given count of connection attempts is greater than or equal to the number given.
The second rule will DROP an incoming connection if:
- The IP address which initiated the connection has previously been added to the list and
- The IP address has sent a packet in the past 60 seconds and
- The IP address has sent more than 3 packets in total.
iptables -I INPUT -p icmp --icmp-type echo-request \ -m recent --set iptables -I INPUT -p icmp --icmp-type echo-request \ -m recent --update --seconds 60 --hitcount 30 -j DROPIn above rules we dont use "--state NEW" since it is not needed in rate limiting number of ICMP echo requests.
NOTE: In the above rules we are trying to automatically limit number of connections from each user. So it is something like 3 attempts from each user in 1 minute.
What if we want to limit number of certain packets from all users ? Then "limit" match option comes to rescue.
"limit" option specifies the maximum average number of matches to allow per second. We can specify time intervals in the format /second, /minute, /hour, or /day, or you can use abbreviations so that 3/second is the same as 3/s.
NOTE: CONFIG_IP_NF_MATCH_LIMIT flag should be enabled in Linux Kernel to use "limit" option.
Let us see how to limit number of ICMP echo requests not more than 3 per second and drop rest of them.
iptables -I INPUT -p icmp --icmp-type echo-request \ -m limit !--limit 3/s -j ACCEPTWhen tuned correctly, this feature allows us to filter unusually high volumes of traffic that characterize denial of service (DOS) attacks and Internet worms.
But take care: When tuned incorrectly, this feature does the opposite: Helping any attacker in denial of service attacks. Instead of having to initiate enough connections to bring the whole server down, it then may be sufficient to just start enough connections to activate the firewall rules.
References:
1. Debian Administration
2. man iptables