Last week (9-15 April). 8,750 failed SSH login attempt, averaging almost one per minute, trying out all kinds of possible user names and left tons of junk in my message log. The recent SSH brute-force attacks (actually it’s not that recent) are rather annoying, and this article at Whitedust.com has useful information on how to prevent this kind of attacks.
For me I have always used AllowUsers directive in /etc/ssh/sshd_config to limit the users that can login. In my setup, I have
AllowUsers root@home-IP my-regular-login
It allows root ssh login, but only from my home ADSL connection with static IP address so I can automate backups. Then it also includes a user ID that I regularly use to log into this VPS. If I need to do some system administration, I’ll use either su or sudo once I am inside.
However I found it is also ideal to slow down the attack when the infested host started to brute force the SSH authentication. There are many scripts/user-land daemons that perform monitoring and blocking. However in a resource limited VPS, I prefer to use something that has less demand in memory/CPU usage. IPTables recent module provides a kernel level solution with little overhead.
This is what I have in my iptables rules:
iptables -N SSH_CHECK iptables -A INPUT -p tcp --dport 22 -m state --state NEW -j SSH_CHECK iptables -A SSH_CHECK -m recent --set --name SSH iptables -A SSH_CHECK -m recent --update --seconds 60 --hitcount 4 --name SSH -j DROP
What it does is:
- Create a new chain
SSH_CHECK, and all incoming SSH connection (TCP port 22) will go into this chain to test the condition. - Condition is, for any source IP address there cannot be more than 3 SSH connection attempts within a 60 seconds window.
- If condition has been met, then all packets from that source IP address will be dropped.
- That source IP can only connect again if condition is cleared again, i.e. there has been 60 seconds of quiet time.
I found it quite effectively and dramatically reduce bot attacks on SSH port. Still, it is important to remove shell access from users that no longer require it, and choose sensible random password that is difficult to guess.

Delicious
Digg
Reddit
Comments
This is pretty cool, and I tried it with iptables 1.3.5 on a recent install of Fedora 5 and it worked as advertised. Unfortunately, it doesn’t work with iptables 1.3.0, which is what is running on my production boxes. When I tried to upgrade to 1.3.5 I got this:
error: Failed dependencies: libc.so.6(GLIBC2.4) is needed by iptables-1.3.5-1.2.1.i386 rtld(GNUHASH) is needed by iptables-1.3.5-1.2.1.i386
And when I tried to install that, I got:
rpm —test —install glibc-2.4.90-17.i386.rpm
warning: glibc-2.4.90-17.i386.rpm: Header V3 DSA signature: NOKEY, key ID 30c9ecf8 error: Failed dependencies: glibc-common = 2.4.90-17 is needed by glibc-2.4.90-17.i386 glibc > 2.3.5 conflicts with glibc-common-2.3.5-10.3.i386
Which looks like a quagmire I’d rather not step in.
Well. RPM hell. That’s why I have been running Gentoo for the last 3 years.
Alternatively you can use the source RPM. You might need to look up RPM manual to work out how to build source RPM, but basically you’ll be able to install a later version of iptables without all those dependency issues, provided the source can be compiled cleanly in your current configuration.
I love this iptables rule … the ssh haven’t really bothered me until some recent punks were hitting my box very quickly and causing bandwidth problems.
Is there a way to modify this rule so we can ban them longer? It seems the 60 second rule applies to the 60 second window as well as the ban time.
Mark
NB: You need a rule AFTER this to allow ssh connections that have gotten through, assuming that is that the last rule in your ruleset is a drop.
I also had to remove the existing ‘allow port 22’ rule that appeared BEFORE this!
I have:
iptables -P INPUT ACCEPT iptables -F iptables -X iptables -A INPUT -p tcp -m multiport —destination-ports 25,80,110,143,443 -j ACCEPT iptables -A INPUT -p icmp -j ACCEPT iptables -A INPUT -p tcp -m state —state ESTABLISHED -j ACCEPT iptables -A INPUT -p udp -m state —state ESTABLISHED -j ACCEPT
prevent dictionary attack
from http://hostingfu.com/article/ssh-dictionary-attack-prevention-with-iptables
iptables -N SSHCHECK iptables -A INPUT -p tcp —dport 22 -m state —state NEW -j SSHCHECK iptables -A SSHCHECK -m recent —set —name SSH iptables -A SSHCHECK -m recent —update —seconds 60 —hitcount 4 —name SSH -j DROP iptables -A INPUT -p tcp -m multiport —destination-ports 22 -j ACCEPT
iptables -A INPUT -j DROP
Hi,
I have a Fedora 4 box that I use as my development server. I tried the above ruleset and it did not work. I am really tired trying out various such iptable recent module rules from different sites/tutorials etc. to prevent brute force attacks, none seems to work for me, not sure why. It must be my mistake, but I am not able to figure it out. Sometimes, it seems like the rules work, but after 3-4 days I again get thousands of failure attempts in my log files.
Here is what I have on my iptables file:
The eth1 is my external interface that is on a public IP address. The —rsource option automatically gets inserted when I do a iptables-save > iptables, I do not type it.
What I do is, edit my iptables file, put the rulset and then restore by iptables-restore < iptables, restart iptables service by service iptables restart, and then save it by iptables-save > iptables. When I save, the —rsource automatically gets added to the rules.
Can anyone help me setting up a correct rule set? My knowledge level is low and I will probably not understand if your answer is short, please forgive my ignorance.
Thanks in advance.
DK,
What I found is,
At the end, if you definitely know where you will be logged in from, it might be better to use iptables rules to limit only these IP addresses/networks. Using “recent” module will only reduce the rate, but will never eliminate the attacks.
Unfortunately I see 30-40 attempts from the same IP address in the same minute. That’s why I say this ruleset is not working. I have iptables 1.3.0 running on my fedora 4 box. Is this the cause?
I find it easier to turn off challenge (keyboard interactive) authentication and exclusively use keys to authenticate. Then I also change the port from 22. On one box I have it on 443 (allows me to poke a hole in most proxy’d networks - then I can jump to whatever box & use my own http proxy & socks proxy) and the others on a random high port.
No more mess in my logs :D
I then have my keys stored in a TrueCrypt volume on my USB thumb drive. This truecrypt volume is copied to my pc & gmail accounts. Also have portable putty & winscp in there too, very helpful :)
It works really good. I tried it in SuSe 10.2. You have to use hooks in /etc/sysconfig/scripts/SuSEfirewall2-custom according to the description and modify options 25, 31 in /etc/sysconfig/SuSEfirewall2, that is
So you can get this IP-chain at the “right position” in the SuSe-Firewall integrated. I have tested it myself from the remote desktop, even though i don’t really need this nice feature (i use only public key identification) it helps to keep your log-files clean.
Where/how to find the list of current banned IP addresses when using iptables?
I mean the current IP addresses that are dropped because of rule:
iptables -A SSH_CHECK -m recent —update —seconds 60 —hitcount 4 —name SSH -j DROP
Banned IP address are found under:
/proc/net/ipt_recent/
To delete an IP address from the file:
echo ‘-[ipaddress]’ >[bannedipfile]
Post new comment