Preventing SSH brute-force attacks with iptables

I wanted to do this tonight and couldn’t remember the exact iptables incantation, and I know I’ll want it again, so sharing it here for me and for anyone else it may be useful to.

If you need SSH to be world-accessible, but don’t want to be plagued by SSH brute-force login attempts, the following ought to do the trick:

iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m limit --limit 3/minute -j ACCEPT

That will allow inbound SSH connections, but only 3 per minute (averaged) – this should be more than a user would normally need, but isn’t sufficient for a brute-force login attack. If someone tries a brute-force attack against you, after a few connections they’ll be ignored.

This is assuming that your default INPUT policy is to drop or reject packets, as it should be. For it to work, it also assumes that you have a rule to allow inbound connections which are part of an established connection – something like:

iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

Of course, if you’re going to open SSH to the world, even with the above protection, you’ll still want to ensure passwords are secure (or disable password-based authentication totally, using SSH keys instead), and I’d recommend disabling root logins via SSH (the PermitRootLogin setting in /etc/ssh/sshd_config)