rackAID

Call Sales: 877-435-2445

Navigation

Resources

How to Block SSH Brute Force Attacks

Posted by Jeff H. 01/27/2010



As I mentioned in an earlier post, ssh attacks are on the rise. If research solutions on combating these attacks, you will often find a long list of tools, most of which are log analyzers that block IPs that repeatedly fail authentication. Popular tools such as fail2ban, denyhosts, and others are subject to attack because they fail to verify log data, so a better method is needed. Fortunately, you have one right there on your server: Netfilter, more commonly known as IPtables.

Rate Limiting SSH with IPTables

You are most likely using Netfilter, aka IPTables, if you are running a recent Linux distro. Most firewalls supplied with hosting control panels or simple setup scripts fail to take advantage of some of the more advanced features available. A feature that can used to combat SSH brute force attacks is a module that remembers recent connections. By tracking recent connections SSH’s port, you can begin to block IP addresses based on the rate at which they connect to SSH. By using IPTables to rate-limit connections, you can mitigate SSH brute force attacks without the mess of third party software or having to deal with ever growing ban lists.

The rules are relatively simple.

/usr/sbin/iptables -I INPUT -p tcp --dport 22 -i eth0 -m state --state NEW -m recent --set
/usr/sbin/iptables -I INPUT -p tcp --dport 22 -i eth0 -m state --state NEW -m recent  --update --seconds 60 --hitcount 4 -j DROP

This rule will block an IP if it attempts more than 3 connections per minute. Notice that the state is set to NEW. This means only new connections not established ones are impacted. Established connections are the result of a successful SSH authentication, so users who authenticate properly will not be blocked. The Debian Administration site has more details on how to rate-limit connections using IPTables.

If you need to see what’s being done, you may want to log these drops. You can do so by setting up a log rule and then using these rules instead.

/sbin/iptables -N LOGDROP
/sbin/iptables -A LOGDROP -j LOG
/sbin/iptables -A LOGDROP -j LOGDROP
iptables -I INPUT -p tcp --dport 22 -i eth0 -m state --state NEW -m recent --set
iptables -I INPUT -p tcp --dport 22 -i eth0 -m state --state NEW -m recent  --update --seconds 60 --hitcount 4 -j LOGDROP

Notice that I’ve changed the rule from DROP to LOGDROP. This way your drops will get logged and you can see the results in your logs:

Jan 27 08:22:29 server kernel: IN=eth1 OUT= MAC=00:30:48:94:fb:21:00:1b:00:00:00:00:00:00 SRC=118.103.140.3 DST=208.43.148.64 LEN=60 TOS=0x00 PREC=0x00 TTL=51 ID=16406 DF PROTO=TCP SPT=31003 DPT=22 WINDOW=5840 RES=0x00 SYN URGP=0 
Jan 27 08:22:29 server kernel: IN=eth1 OUT= MAC=00:30:48:94:fb:21:00:1b:00:00:00:00:00:00 SRC=118.103.140.3 DST=192.168.1.1 LEN=60 TOS=0x00 PREC=0x00 TTL=51 ID=5076 DF PROTO=TCP SPT=45354 DPT=22 WINDOW=5840 RES=0x00 SYN URGP=0 
Jan 27 08:22:35 server kernel: IN=eth1 OUT= MAC=00:30:48:94:fb:21:00:1b:00:00:00:00:00:00 SRC=118.103.140.3 DST=208.43.148.66 LEN=60 TOS=0x00 PREC=0x00 TTL=51 ID=37295 DF PROTO=TCP SPT=21077 DPT=22 WINDOW=5840 RES=0x00 SYN URGP=0 
Jan 27 08:22:35 server kernel: IN=eth1 OUT= MAC=00:30:48:94:fb:21:00:1b:00:00:00:00:00:00 SRC=118.103.140.3 DST=208.43.148.64 LEN=60 TOS=0x00 PREC=0x00 TTL=51 ID=16408 DF PROTO=TCP SPT=31003 DPT=22 WINDOW=5840 RES=0x00 SYN URGP=0 

Effectiveness
I always try to get a sense of effectiveness of any tool or configuration we deploy. I find many “security” tools that are popular amongst the web hosting crowd provide little to no value. In many cases, appropriate configuration of your server or web application could achieve similar results without the hassle of maintaining a third party product.

Are the IPTables rules effective? In short yes.

During a recent attack on a server, the SSH service remained fully accessible with no service interruption.

Previously such aggressive attack would have caused service interruptions. So on the service side, this approach works. When I dug into the logs, I found three failed user attempts against SSH prior to the rate-limiting kicked in. The attack then sent 67 more attempts before it gave up.

Pros and Cons
The benefit of this approach is you don’t need any added software. IPtables is likely sitting on your server already if not already in use. There are no cumbersome ban lists to clear out or fix. The rate of false positives should be low as legitimate user should not trip the limits. If you have some automation tools tripping the limits, you could white list these by allowing them before the rate-limiting rule or raise the limits.

One of the drawbacks is that this approach does not lock accounts. A slow, distributed attack could fall under the radar. If it was a directed attack against a specific user account, the attacker could churn away for days or weeks without detection. For that, you would need something that can lock user accounts after failures. PAM includes a module called pam_tally that does just this. If you fail too many times, an account is locked.

Stay Tuned
In addition to these IPTables settings, there are some things you can do within SSH itself to harden the service from attacks. I will cover those in my next post on SSH.

Bookmark and Share

Comments

Jason commented on How to Block SSH Brute Force Attacks

Jason · 03/07/2010 01:49 am

Great article. Thank you for posting this. The other methods I had seen for blocking ssh attacks were all hackish bash or perl scripts. This is much more elegant.

Juli Z commented on How to Block SSH Brute Force Attacks

Juli Z · 03/15/2010 10:20 am

I find this method works very well.  We also use it on cPanel and Plesk to protect their admin areas. Just change port 22 to the port you need to block.

Chip commented on How to Block SSH Brute Force Attacks

Chip · 04/26/2010 04:16 am

Just tried this guide out but can’t unfortunaley get this to work properly. I’m trying to use the one where you collect the logs but at the last command:
iptables -I INPUT -p tcp—dport 22 -i eth0 -m state—state NEW -m recent —update—seconds 60—hitcount 4 -j LOGDROP
I’ll get this error:
iptables: Too many levels of symbolic links.
Any thoughts on how too solve this? Haven’t done the first where you just drop the logs since it’s important that I have the logs

Jeff H. commented on How to Block SSH Brute Force Attacks

Jeff H. · 04/26/2010 08:34 am

There was a typo in the first rule.  “-set” should have been written “—set”.

/usr/sbin/iptables -I INPUT -p tcp —dport 22 -i eth0 -m state —state NEW -m recent —set

Alex Wu commented on How to Block SSH Brute Force Attacks

Alex Wu · 05/09/2010 05:53 am

Hi jeff, i’m new to ssh and I have the same problem as chip.
The setup without logs works fine but the setup with the logs fails at the last step:
iptables -I INPUT -p tcp—dport 22 -i eth0 -m state—state NEW -m recent —update—seconds 60—hitcount 4 -j LOGDROP
Too many levels of symbolic links.

You were quick to point out that there was a typo, but I don’t think so as I’ve tried with the new command and it doesn’t recognize it.
I’ve noticed that the only difference from the last command and the one without the logs is the change from DROP to LOGDROP. Otherwise it works. Could it be a problem in the way “LOGDROP” is setup?
Thank you very much for the article.

chrissy commented on How to Block SSH Brute Force Attacks

chrissy · 06/05/2010 05:02 pm

Chip and Alex, I just did a quick search in the manpage for iptables, and it recommends using the rules as described in the article—except “LOGDROP” should simply be “DROP”.  The exact quote in the manpage is “So if you want to LOG the packets you refuse, use two separate rules with the same matching criteria, first using target LOG then DROP (or REJECT).”  So the first rule should jump to the “LOG” chain, and then the second rule should jump to the “DROP” chain.  As both rules check for packets matching the same criteria, those matching packets would effectively be logged and then dropped.  I may be wrong or this may be entirely different from the error you’ve been experiencing, but this is my understanding of the method’s correct usage.

Jeff H. commented on How to Block SSH Brute Force Attacks

Jeff H. · 06/07/2010 02:17 pm

The LOGDROP is just a custom rule. It is not anything special.  In iptables you can create custom rules.  I just called it LOGDROP so I know it will log the request and then drop it.  I will double check it when I get a chance to be sure I did not make an error.

I like using custom rule names so I can then easily drop packets into them from the main rule change.

This approach makes iptables more modular.

Alex Wu commented on How to Block SSH Brute Force Attacks

Alex Wu · 06/07/2010 05:07 pm

Thanks chrissy and jeff. I actually found a similar solution thanks to ufw (uncomplicated firewall), a cli frontend for iptables easy configuration. It has far less flexibility I guess but it’s perfect for my needs.
It was developed by Canonical (Ubuntu), but being opensource I guess should be available in other distributions as well.
Well if you end up installing it the only commands you need to use are these:
ufw default deny incoming
ufw limit in log 22/tcp
ufw enable
1st command this will set deny incoming connections by default.
2nd command will allow traffic through the 22/tcp port and keep a log of it. It will also block any ip address that has attempted to initiate 6 or more connections in the last 30seconds.
The last command enables the firewall.

A thing to note is that ufw will write back the configuration to iptables everytime the system is booted, so there’s no need to fiddling around with startup scripts to get the firewall rules automatically set again when rebooted.
And that’s all, my needs for a firewall are really basic and this little thing does what I need.

I hope it was helpful, thanks.

Add Comment

Notify me of comments?