In 2005, hackers started using "brute force." These types of attacks target Secure Socket Shell (SSH) daemons running on port 22 and use dictionary attacks against them to blindly guess usernames and passwords (see infinite-monkey theorem). There are a number of ways to defend against these attacks: changing the port the daemon runs on; using log parsing tools to dynamically block source IP addresses; port knocking; and a number of methods using iptables, to name just a few.
But not all of these options suit every environment. Many organizations have limitations, such as an infrastructure that requires SSH to be running on port 22, making some methods problematic. Here we'll focus on three iptable-based methods for mitigating the risk of brute-force SSH attacks: limiting the source, using the "recent" module, and using the "limit" module.
SSH rules in iptables
Let's start by looking at some basic SSH rules in iptables. I have displayed the rules in the iptables-restore format. You could add these rules manually by prefixing them with the iptables user space command.
-A INPUT -m state --state ESTABLISHED,RELATED -m tcp -p tcp --dport 22 -j ACCEPT -A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
The first rule tells iptables to allow any established or related connections on port 22. The second rule allows new connections to be initiated to port 22. The combination of these two rules allows anybody, from anywhere, to connect to a host on port 22 and will likely make a host the target for brute force attacks.
Secure this by limiting it only to a single source.
-A INPUT -m state --state NEW -m tcp -p tcp –s 22.214.171.124 --dport 22 -j ACCEPT
The –s option is added to indicate source. This restricts SSH connection attempts to the host 126.96.36.199. By using the –s option, we can also specify a subnet by supplying the appropriate net mask.
-A INPUT -m state --state NEW -m tcp -p tcp –s 188.8.131.52/24 --dport 22 -j ACCEPT
Now SSH connection attempts will be allowed from the 184.108.40.206/24 Class C address space.
But this will not solve the problem if it is necessary to access the daemon from a wide variety of locations (for example, a roaming user without a fixed set of addresses or a user from a dynamic address space such as a residential broadband connection). There are two ways to address this. Both methods use iptables modules. The first module is 'limit'.
Using limit, recent
The limit module allows you to limit connection rates. On the following lines you can see some rules that make use of this module:
-N SSH_LIMIT -A INPUT -m state --state NEW -p tcp --dport 22 -j SSH_LIMIT -A SSH_LIMIT -m state --state NEW -m limit --limit 2/min --limit-burst 2 -m tcp -p tcp --dport 22 -j ACCEPT -A SSH_LIMIT -m tcp -p tcp --dport 22 -j DROP
First we create a new chain called SSH_LIMIT. We then refer all new SSH connections to this chain (this assumes we have another rule for established connections as we don't want to impact them). The chain uses the limit module to allow a burst of up to two connection attempts. If this is exceeded, future connections are limited to two attempts per minute. If the limit is not hit for a minute, the burst is reset and the limit removed.
The following rules create something similar to the previous module:
-N SSH_RECENT -A INPUT -m state --state NEW -p tcp --dport 22 -j SSH_RECENT -A SSH_RECENT -m recent --set --name SSH -A SSH_RECENT -m recent --update --seconds 60 --hitcount 3 --name SSH -j DROP
These rules create a chain called SSH_RECENT, passing all new SSH connections to the chain (again excluding established connections). Using this module a server allows a maximum of two connections attempts per minute for each source IP address. If there are more than two connections, subsequent connections will be dropped until no new connections appear for an interval of 60 seconds.
Each module behaves slightly differently. 'Limits' uses thresholding while 'recent' blacklists source IP addresses when they attempt more than the prescribed number of connections, but both protect your host from brute force attacks.
While these iptables methods are useful, SSH rules alone are not a cure-all. Take precautions by ensuring your users select strong passwords, limiting SSH access (and/or shell access) only to users who need it, and limiting users to only those functions which they require.
About the author: James Turnbull is the author of Hardening Linux and a security consultant at the Commonwealth Bank of Australia. He is also the resident security expert for SearchEnterpriseLinux.com.