Debian – Use iptables rate limiting to temporarily block FTP server brute-force attempts

brute-force-attacksdebianfirewallftpiptables

This is along a similar line to other posts on brute-force attacks, but a bit more specific:

We are able to enforce decent passwords, generally, and user name policy also avoids falling prey to what 99.9% of the brute-force FTP stuff is trying… but I see no reason to allow thousands of attempts endlessly, and they can sometimes make fill the log files with lots of noise that makes it harder to find potentially more targeted things.

So, for passive FTP, would some sane rate-limiting in iptables for incoming TCP 21 be reasonably effective at cutting off the massive numbers of failed attempts while not ever getting in the way of normal use? I presume that this would be done via rate-limiting connections from the same IP to TCP 21.. is that correct? Are there problems I'm not thinking of there?

Next, then; what would you suggest for a simple iptables command on a bastion firewall/router to just put in some protection against the hardest/fastest hitting brute-force attacks? My thinking would be something along the lines of a trigger of 25 connections (on the principle that a successful login would be only a single connection to TCP 21) within a minute or so, and then a block for a half hour. Do those numbers seem reasonable?

(other info: this is for a debian firewall/router which protects a DMZ of mixed OSs)

Best Answer

iptables -A INPUT -p tcp -m state --state NEW --dport 21 -m recent --name ftpattack --set
iptables -A INPUT -p tcp --dport 21 -m state --state NEW -m recent --name ftpattack --rcheck --seconds 60 --hitcount 4 -j LOG --log-prefix 'FTP REJECT: '
iptables -A INPUT -p tcp --dport 21 -m state --state NEW -m recent --name ftpattack --rcheck --seconds 60 --hitcount 4 -j REJECT --reject-with tcp-reset

these rules near or at the top of your ruleset will allow only three connections to port 21, from any given IP address, in a rolling 60-second window. To allow n, use --hitcount n+1; to use a bigger window than 60 seconds, increase --seconds 60.