» Block brute force attacks with iptables
Since 2005 there has been an immense increase in brute force SSH attacks and though Linux is pretty secure by default, it does not stop evil programs from indefinitely trying to login with different passwords. Without proper protection your server is a sitting duck waiting for a bot to guess the right combination and hit the jackpot. But with just 2 commands we can stop that.
Symptoms
Here's an example of the auth.log file. You can see that even as I'm writing this article bots are trying different account combinations to get into my server:
Jul 28 21:32:16 impala sshd[10855]: Illegal user office from 213.191.74.219
Jul 28 21:32:16 impala sshd[10855]: Failed password for illegal user office from 213.191.74.219 port 53033 ssh2
Jul 28 21:32:16 impala sshd[10857]: Illegal user samba from 213.191.74.219
Jul 28 21:32:16 impala sshd[10857]: Failed password for illegal user samba from 213.191.74.219 port 53712 ssh2
Jul 28 21:32:16 impala sshd[10859]: Illegal user tomcat from 213.191.74.219
Jul 28 21:32:16 impala sshd[10859]: Failed password for illegal user tomcat from 213.191.74.219 port 54393 ssh2
Jul 28 21:32:16 impala sshd[10861]: Illegal user webadmin from 213.191.74.219
Jul 28 21:32:16 impala sshd[10861]: Failed password for illegal user webadmin from 213.191.74.219 port 55099 ssh2
Do you see the rate at which this is happening? Nowadays' connection speeds allow for crackers to try an enormous amount of combinations every second! It's time to stop this before someone hits the jackpot and my server is compromised.
About iptables
Iptables is the standard Linux firewall and though I use Ubuntu, it should be installed by default on any modern distribution. But it doesn't do anything yet. It's just sitting there, so we need to teach it some rules to prevent brute force attacks.
There are tools available to do this for us like fail2ban. Though it's a great piece of software and certainly has it's advantages, in this article I'd like to stick with iptables because fail2ban parses log files to detect brute force attacks at a certain interval, whereas iptables works directly on the kernel level. Besides I don't think many people know about iptables' full capabilities, and it comes preinstalled!
Easy setup - just 2 rules
Because iptables comes standard with every Linux distribution we'll skip right to setting up the specific firewall rules we need. In depth configuring of iptables takes a bit of understanding and is not within the scope of this article, but let's take a look at these two statements:
sudo iptables -A INPUT -i eth0 -p tcp --dport 22 -m state --state NEW -m recent --set --name SSH
sudo iptables -A INPUT -i eth0 -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 8 --rttl --name SSH -j DROP
The -i eth0 is the network interface to which ssh connections are made. Typically this is eth0, but maybe you need to change it.
That's it! Together they will rate-limit all incoming SSH connections to 8 in a one minute window. Normal users will have no trouble logging in, but the brute force attacks will be dropped, limiting the number of possible account combinations from unlimited, to 8. That's awesome!
failsafe
While you're still testing, you might want to add the following line to your crontab
*/10 * * * * /sbin/iptables -F
This will flush all the rules every 10 minutes, just in case you lock yourself out. When you're happy with the results of your work, remove the line from your crontab, and you're in business.
Advanced Setup - want more?
Restore on boot
You will find that on your next reboot, the rules are lost. Damn! You probably want these 2 brute force protection rules automatically restored, right? The most elegant way would probably be to restore the iptables rules when your network interface comes back online. Here how I would this on Ubuntu. Let's get the following content in a file: /etc/network/if-up.d/bfa_protection
#!/bin/bash
[ "${METHOD}" != loopback ] || exit 0
/sbin/iptables -A INPUT -i eth0 -p tcp --dport 22 -m state --state NEW -m recent --set --name SSH
/sbin/iptables -A INPUT -i eth0 -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 8 --rttl --name SSH -j DROP
Save the file and make it executable:
chmod u+x /etc/network/if-up.d/bfa_protection
Now every time your interface comes up, the rules are added to iptables. Sweet.
Remove on shutdown
But to do this really clean, we need to have a script that removes the rules as well for when the interface goes down. Just to make sure the rules are never added twice. So let's also create a file: /etc/network/if-down.d/bfa_protection
#!/bin/bash
[ "${METHOD}" != loopback ] || exit 0
/sbin/iptables -D INPUT -i eth0 -p tcp --dport 22 -m state --state NEW -m recent --set --name SSH
/sbin/iptables -D INPUT -i eth0 -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 8 --rttl --name SSH -j DROP
-D removes a rule whereas -A adds one. Anyway. Let's save this file and make it executable:
chmod u+x /etc/network/if-down.d/bfa_protection
That's it! We're in business!
Like to test it?
Very wise indeed, well iptables -L shows active rules so why not execute the following:
/etc/network/if-up.d/bfa_protection
iptables -L
And now there should be something like this in your terminal:

Perfect. If you have another machine (not the one you're working on! you do not want to take the risk of getting banned yourself!) you could really test it by logging 8 times within 60 seconds. See if you get banned!
Now does the removal script work as well?
/etc/network/if-down.d/bfa_protection
iptables -L
Now the rules should be gone.
Undo
And oh yes, if at any time you run into problems, the following command will flush all the iptables rules:
iptables -F
And you can undo by just removing the files we created:
rm /etc/network/if-up.d/bfa_protection
rm /etc/network/if-down.d/bfa_protection
iptables -F # flush all the rules, just in case
More on iptables
This is just one nice example of what you can do with the iptables firewall but there are many other uses for iptables in order to secure your system. There are scripts / wizards that will help you setup iptable rules like ksecure_firwall (a bash script by myself), or more widely used programs like fwbuilder or firestarter (both available through package managament like apt).
If you'd like to know more about iptables, this is a place to start, or you could just google of course.
Stay up to date
You can track my blog
articles and
comments. You may also find my
bookmarks interesting. Or
Follow me on Twitter
Like this Article?
|
Your money is no good here, but you can boost morale by spreading the word! : ) |
RelatedArticles like this one» Make SSH connections with PHP |
tags: ubuntu, security, linux, iptables, firewall, ssh
category: Howto - Security
read: 173,223 times






tagcloud
#109. Michael on 02 September 2010
Thanks so much for all of your fantastic articles :)
#108. Malcolm on 28 August 2010
Thanks
#107. Reino on 03 July 2010
#106. Kevin on 29 June 2010
@ Rian Inso: It's not a real ban as in it allows you to only make a fixed number of requests per timeframe you specify. So after that you're good to go.
#105. Rian Inso on 25 June 2010
In absence of flushing the tables, how long do the bans last?
FYI, on RHEL/CentOS one can simply add the following lines before their ssh rule:
... [more]
-A RH-Firewall-1-INPUT -i eth0 -p tcp --dport 22 -m state --state NEW -m recent --set --name SSH
-A RH-Firewall-1-INPUT -i eth0 -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 8 --rttl --name SSH -j DROP
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
#104. Reino on 14 June 2010
I tested it again without all the other ssh rules i had before and same thing happened, so there's no conflict with other rules. I only had rules for allowing established connections to receive traffic, allowing incoming web traffic and final rule for dropping everything else which isn't accepted before that..
#103. Kevin on 10 June 2010
@ Fajar Priyanto: Yeah pretty nice eh? : )
@ Pascal: All credits go to iptables. Powerrr.
#102. Pascal on 10 June 2010
#101. Fajar Priyanto on 25 May 2010
I didn't know iptables can do that. LOL. Cool.
#100. aravind on 16 May 2010
#99. Kevin on 15 May 2010
and add
@ Foam Roofing: That works great if your server is located in your basement, yes.
@ Steven: Cool!
#98. Steven on 11 May 2010
I talked about it more on:
http://www.linuxquestions.org/questions/linux-networking-3/using-nat-on-multiple-subnets-806806/
#97. Foam Roofing on 10 May 2010
I simply deny all ips from access via SSH on my server, and I don't even allow FTP.
You can't hack what you can't touch.
#96. daniel on 03 May 2010
-A INPUT -i eth0 -p tcp --dport 22 -m state --state NEW -m recent --set --name SSH
-A INPUT -i eth0 -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 8 --rttl --name SSH -j DROP
... [more]
(i.e., same as your steps above just in config format rather than as commands)
Thanks again for this great tip!
#95. Kevin on 24 April 2010
#94. Charles Stepp on 19 April 2010
#93. Ramito on 16 April 2010
Why not use the command "service iptables save" to save the config, instead of the if-up.d and if-down.d config files ?
Rami
#92. Kevin on 21 February 2010
#91. Jerry on 08 February 2010
Make sure you got the "recent" module enabled in the kernel. (in the netfilter tree) I had the same problem.
@Kevin : Thnx for sharing... didn't know
#90. Kevin on 07 January 2010
#89. John G. on 27 December 2009
iptables: No chain/target/match by that name
#88. Kevin on 06 December 2009
#87. S2m on 04 December 2009
I have one script that depends on the conditions make some N amount of SSH connections to the server.
If I just use example that was brought earlier the script will be banned sometime.
... [more]
Is it possible to use ssh-brute-force iptables rules but with user exception? That user "John" can make any amount of connections?
Thanks.
#86. Chris M on 13 November 2009
#85. Kevin on 04 September 2009
#84. Donn Lee on 02 September 2009
#83. Kevin on 12 April 2009
@ Ankit: something like:
@ Raul Luna: Thx!
#82. Raul Luna on 11 April 2009
I love your rules!!! I've installed them on my SuSE to get rid of those nasty script kiddies and they worked great!!!
Moreover, I recently used them to prevent attacks to my website. I am testing the rules right now, but they seem to work fine!!
... [more]
Keep up the good working.
#81. Ankit on 06 April 2009
#80. mrwes on 03 April 2009
#79. Kevin on 11 February 2009
#78. hmm on 08 February 2009
#77. Doug on 06 February 2009
#76. Kevin on 30 December 2008
#75. Derek Johnson on 29 December 2008
(http://denyhosts.sourceforge.net/) which can automatically lock out any IP address that tries to connect using a bogus username and/or password.
It's also worth changing the default ssh listening port.
#74. Kevin on 10 December 2008
#73. Robert White on 06 December 2008
The line below should be included in the bulk of your iptables rules. Of course you should make sure that this port 22 line is before any others relating to that port.
#72. Robert White on 06 December 2008
#71. Kevin on 01 December 2008
@ kamikaze.cockroach: That would be security by obscurity and is not at all considered to be good protection, it may also break processes (rsyncs, whatever) that already have been configured to connect to port 22.
#70. Craig Fowler on 27 November 2008
With what you describe here, you open yourself up for a denial-of-service attack. Someone could lock you out of ssh on your own server by constantly establishing TCP connections on port 22. They don't even have to attempt a username/password against ssh - just establish the connection then drop it.
Your rate keeps getting maxed out, which prevents legit connections.
... [more]
Denyhosts is specific to ssh, but it allows rules along the lines of:
IF x failed authentications on ssh per Y period of time, ban the attacker's IP for Z duration
I believe denyhosts uses iptables internally, but it's a great solution for what you're trying to do here.
#69. kamikaze.cockroach on 26 November 2008
#68. Kevin on 10 October 2008
#67. ThisGuy on 09 October 2008
To work around it, all you need to do is this:
Use "iptables -I INPUT [rulenumber] ..."
... [more]
where [rulenumber] is the location in your iptables rules list where you want to insert the rule...a little trial and error is required to stick it in the right spot (just before/above the ACCEPT rule for the same port, I suggest), but once you get the right number, you should be fine.
Our community support is the strongest on the planet! Thanks everyone!
#66. Ron Doron on 24 August 2008
Thanxx in advance
#65. Avi on 29 July 2008
#64. Kevin on 17 July 2008
Especially when automating things and when this is potentially used on so many servers. You cannot afford sloppiness (when other people start using your information).
Black holing Asia sounds like permanently staying indoors to avoid rain. Some people out there might actually need to allow connections from Asia. Some people might prefer an umbrella.
... [more]
Changing the port could help a lot. There are many ways. I write about one I think hasn't been getting enough attention.
I've edited your comment because I do not tolerate curse words on my site.
#63. rob on 28 June 2008
Also, like someone said early on, just change ports and that will block the millions of script kiddie, I think I'm a hacker cuz I downloaded this program and can type in IP addresses people. Also think about what your server is used for people. If you resolve that dang log file, where do nearly ALL of the IPs fall? APNIC... ASIA... Just put IP blackholes for all of China and Korea and be done with it already. I used to have 800+ attacks on my box per day, then I woke up and was like, gee, this webserver is only meant to serve people on campus here in texas... why do I need to have it available to the world for? So I blackholed china and korea, most of it at least, about a dozen entries, 202.0.0.1/8 and so on... And the attacks miraculously, stopped.
If you're not feeling like typing install some IDS software or better yet have someone who understands networking install a freakin' ASA or something on your network.
... [more]
Bottom line, if you don't know what you're doing learn. Don't just cut and paste things off a website and expect to be secure.
ok I'm done.
~R
#62. makkksimal on 18 June 2008
And as always there a many ways to get what you like and need :)
#61. Kevin on 18 June 2008
#60. makkksimal on 17 June 2008
i think it is build in in ubuntu/debian
for further information tortoure you man pages
... [more]
man iptables-save
man iptables-restore
#59. Kevin on 31 May 2008
#58. Simon on 31 May 2008
#57. Chris on 10 May 2008
#56. Melvin on 28 November 2007
Very useful, thanks!
#55. Michael on 28 November 2007
I tried to install a port 22 throttle into my Iptables once before but the example lines didn't work. Yours worked just fine. One change I did make, though was to change the DROP to a REJECT --reject-with tcp-reset
(Those folks who run those bots annoy me! <G>)
... [more]
Thanks again!
P.S. Oh, and one thing I've never been able to get to work on my FC system (for two distros now) is for my own Iptables to "take" on startup. I can get on the Net, but my intranet machines can't until I drop the firewall (flush all the chains, etc.) and the restart it. This, even though I have "service iptables save" as the last line in my script, so that the chains are saved into the file FC reads on startup.
Thanks again!
#54. Kevin on 19 October 2007
But I think more elegant that the rules become active when networking comes up, and clear when it goes down.
There must be a Red Hat equivalent for the /etc/network/if-up.d method, but I just don't know Red Hat (clones) that well. So maybe you'd better ask them or their communities how to do it.
#53. Carl on 14 October 2007
And I see I'm not the only one (there are some others asking the exact same thing in the comments, yet nobody responded..).
#52. Andrew on 04 October 2007
#51. Kevin on 23 September 2007
#50. Pete on 22 September 2007
Maybe I'm just nit-picking though, because apart from that it's a really well-written and informative article
#49. erth64net on 20 September 2007
#48. Mukund on 12 September 2007
#47. Nphyx on 07 September 2007
The issue isn't of whether they're going to break in really. It's the amount of bandwidth (1gb/day for me for the last 3 days here) and the size of the logs (about 1mb per day). Not only does that add up fast, it makes it nearly impossible to check the logs to see what legitimate users are doing. As amusing as it is to watch 8 synchronized bots chew through a dictionary of passwords each day on every common user name starting with "Administrator" I only need a couple entries to send off a nastygram to their ISPs :)
#46. Nphyx on 07 September 2007
#45. Chiron on 21 August 2007
#44. math on 11 August 2007
Imagine if you used 8 char passwords instead! (now we're looking at 2.2 million years.)
This all assumes you arent noticing 100 attacks per second (!). Thats nearly a dos attack at that rate, and serious neglect of managing the huge log files that would result. (200 chars per attempt there. at 100 attempts/s * 200 chars we're looking at 20K/SECOND, or nearly 2 GIGS a day.
... [more]
So.
I think its better to put your effort into securing things that are really hackable, like that php script you wrote that no one else on the planet is using (thus you arent benefitting from 10,000 eyes on your code). Not to mention just plain not using a windows box to login to your unix servers, ever, cuz then they have your root password.
#43. Digerati on 10 August 2007
which is loaded with several scripts.
Not sure what to do.
#42. Kevin on 06 August 2007
#41. Daniel on 06 August 2007
Great article. Just one question.
The two rules are protecting us from "out side", but if the attack come from the internal network What do we need change in the rules ?
... [more] Bests
#40. Zigzo ZLinks on 05 August 2007
#39. Kevin on 03 August 2007
#38. Geog on 02 August 2007
I do this with -m limit. I haven't thought
about -m recent.
#37. Kevin on 02 August 2007
#36. Jay Fude on 02 August 2007
#35. Anon on 02 August 2007
The trouble with 8 per minute is that there is still a very small chance that one of those 8 tries hits your userid/password combo. At which point the attacker has your machine, even with your iptables rules.
#34. Thomas Mathiesen on 02 August 2007
#33. dany on 02 August 2007
http://www.hexten.net/wiki/index.php/Pam_abl
#32. psychicist on 02 August 2007
A brute force attack on such a configuration might be possible but requires some really heavy-duty supercomputer. If you upgrade to newer OpenSSH versions and encryption strengths there is not much to be broken into.
#31. Peter N. M. Hansteen on 02 August 2007
#30. Erm on 01 August 2007
tail -f /var/log/syslog/var/log/syslog
What's really fun is to do a whois on the ip that's doing the brute force attack, call their isp, and tell them one of their ips is doing a dictionary attack on your ssh server. Then if you hear a gulp ... you can tell THEY were the ones doing it. Classic.
... [more]
Personally I like denyhosts because you can set it up to contact their database, and get even more protection against attackers. I like the thought of being able to access my computer from anywhere in the world.
#29. Vinas on 31 July 2007
#! /bin/sh
# rate-limit connections to sshd
iptables -A INPUT -p tcp --syn --dport 22 -m recent --name sshattack --set
... [more] iptables -A INPUT -p tcp --dport 22 --syn -m recent --name sshattack --rcheck --seconds 300 --hitcount 3 -j LOG --log-prefix 'SSH REJECT: '
iptables -A INPUT -p tcp --dport 22 --syn -m recent --name sshattack --rcheck --seconds 300 --hitcount 3 -j REJECT --reject-with tcp-reset
#28. linuxtraveler on 31 July 2007
I didn't know this module!
#27. Asktheadmin on 31 July 2007
#26. kentborg on 31 July 2007
I would recommend against a non-standard port. It will confuse good users, it won't stop the bad guys, and it might make you complacent about maintaining your machine *and* having good passwords that are not reused elsewhere on the net.
-kb
#25. foutrelis on 31 July 2007
What should I do? What rules does it need? :P
Thanks in advance and keep up the great work! :)
#24. Lean Fuglsang on 31 July 2007
I mean, it is possible that a bruceforce attack will make it impossible for all IP adresses to login?
#23. Zotter on 31 July 2007
If you'd like to be preemptive and lock out known attackers even before they start on your box - try Denyhosts and use the shared database options.
http://denyhosts.sourceforge.net
... [more]
Think along the lines of a DNSRBL for ssh brute forcers. But one where the attackers pretty much have to prove themselves as attackers to get listed.
#22. Hyper Viper on 31 July 2007
#21. Matt on 31 July 2007
Some interesting things in this file:
Port 2222
... [more] PermitRootLogin no
MaxAuthTries 2
AllowUsers ::YOURUSER::
yep...
#20. Isolder on 31 July 2007
#19. DB on 31 July 2007
#18. SnortSam on 31 July 2007
#17. BobsUrUncle on 31 July 2007
#16. Kevin on 31 July 2007
All Operating Systems have their flaws, but I think it's like Churchill's famous dictum: "Democracy is the worst form of government, except for all those other forms that have been tried from time to time." Maybe this goes for Linux too ;)
#15. OMFG on 31 July 2007
#14. Kevin on 31 July 2007
But I wrote this article just to show people that there are different ways. And I felt iptables has a lot to offer that many of us don't know about.
Each way has it's own advantages and it's up to the end user to decide which one suits the situation best.
#13. Craig on 30 July 2007
/sbin/iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 22 -j DNAT --to $ssh_server:22
/sbin/iptables -t nat -A POSTROUTING -p tcp -s #ssh_server --sport 22 -j SNAT --to $externalIP:22
#12. Juan Sabor on 30 July 2007
#11. gHOST on 30 July 2007
#10. Reid Ellis on 30 July 2007
iptables -A INPUT --protocol tcp -i eth0 -m state --state NEW --dport 22 -m recent --update --seconds 10 -j DROP
iptables -A INPUT --protocol tcp -i eth0 -m state --state NEW --dport 22 -m recent --set -j ACCEPT
... [more]
iptables -A INPUT --protocol tcp --dport ssh -m limit --limit 3/minute --limit-burst 2 -j ACCEPT
I got this a while back (~2-3 yrs ago?) after searching for good iptables rules, and it seemed to do the trick, stopping brute force attacks.
#9. lazy-bit.ch on 30 July 2007
#8. Casey on 30 July 2007
#7. Chuck on 30 July 2007
#6. gris on 30 July 2007
http://denyhosts.sourceforge.net/
#5. Azmith on 30 July 2007
#4. Kevin on 30 July 2007
#3. Lukas Meyer on 30 July 2007
In the beginning of the script add:
if [ "$METHOD" = loopback ]; then
exit 0
fi
... [more] ...to ensure that it isn't run on lo-interfaces.
furthermore you have the certain interfaces name in $IFACE
one could simply insert $IFACE instead of eth0. Works great if let's say, you travel a lot and change from wired to wireless networks all the time...
#2. Kevin on 30 July 2007
There should a a scrollbar. If your scroll to the right you will see that the rules are not identical. The first one identifies SSH traffic and the second one drops the traffic under specific circumstances.
SSH is TCP only, so no need for dropping UDP traffic in this example.
... [more]
Could it be that your browser is not showing the scrollbars correctly? I've tested on ubuntu/firefox2 and windows/ie6+7
#1. Bob Clay on 30 July 2007