If you have SSH open toward the Internet, you are surely aware of the number of brute force password attempts your server sees everyday. Although a good password policy may make these attempts nothing more than an annoyance, each connection to your SSH daemon takes up valuable server resources. I was tired of seeing thousands of password attempts every day, and decided to limit the rate at which hosts could connect to my SSH daemon using iptables.

I use RHEL5, so I added the following lines to /etc/sysconfig/iptables:

-A RH-Firewall-1-INPUT -m state --state NEW -m recent -p tcp --dport 22 --set
-A RH-Firewall-1-INPUT -m state --state NEW -m recent -p tcp --dport 22 --update --seconds 60 --hitcount 4 -j DROP
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT

The first line sets up the session tracking. The second line, tells iptables that if it receives 4 or more connection attempts within a 60 second window to drop the packet. Finally, the third line allows incoming SSH attempts should they not meet the drop criteria. This line is vital, but easy to overlook.

After saving the file, service iptables restart will restart iptables with the new changes. You can see your new ACL at work with the following command:

# iptables -L -v
pkts bytes target     prot opt in     out     source               destination
<snip>
  24  1368            tcp  --  any    any     anywhere             anywhere            state NEW recent: SET name: DEFAULT side: source tcp dpt:ssh 
   14   756 DROP       tcp  --  any    any     anywhere             anywhere            state NEW recent: UPDATE seconds: 60 hit_count: 4 name: DEFAULT side: source tcp dpt:ssh 
   10   612 ACCEPT     tcp  --  any    any     anywhere             anywhere            state NEW tcp dpt:ssh 

As you can see, my server has already dropped 14 incoming connections because they were coming too frequently.

You can find more information on this concept at MNX Solutions and HostingFu.