» 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.


Like this article?

   Then Digg it!
Or use another bookmark button below to show your support &
help me spread the word.


tags: ubuntu, security, linux, iptables, firewall, ssh
category: How to - Security
read: 63,863 times

Add comment

» Currently away on vacation. I can reply your message the 24th of July 2008. Please post anyway and check back then. Thank you!

for syntax highlighting

[CODE="Javascript"]
your_code_here();
[/CODE]

Replace "Javascript"
with "php", "text", etc.
code (to make sure you are not a spammer)

Comments

#63. rob on 28 June 2008

robok i've read alot of posts here and now I have to chime in. First off, in red hat flavored distros like CENTOS for instance, /etc/sysconfig/iptables has all the config lines in it, just like you'd type them, minus of course the "iptables" so you can just stick your entries in there. Every time you restart, which on a good running box is like what? Never? It will reinstate the same rules. I can't see any freaking point at all in removing the rules when you shut down the interface, wasting that time making a script, if, when the interface is SHUT DOWN NOBODY WILL BE SSH'ing TO IT SINCE ITS NOT -=THERE=-

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... Fucking ASIA... Just put IP blackholes for all of fucking 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... WTF 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 shit off a website and expect to be secure.

ok I'm done.

~R

#62. makkksimal on 18 June 2008

makkksimalMaybe its a matter of preference. I use iptables-save and restore with my init scripts for years and find it very comfortable. But your right.. you need scripting anyway.

And as always there a many ways to get what you like and need :)

#61. Kevin on 18 June 2008

Kevin@ makkksimal: Thanks for pointing that out. To keep the article compact I choose to use scripting and ignore the iptables-save & restore, since with iptables-restore you would still need scripting anyway. Scripting also offers greater flexibility in my humble opinion.

#60. makkksimal on 17 June 2008

makkksimali guess iptables-save and iptables-restore should be mentioned somewhere.. this is the easy buildin way of saving and restoring the tables.. (who could have thought that? ;) )

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

Kevin@ Simon: this is the maximum per IP.

#58. Simon on 31 May 2008

SimonSo you say "rate-limit all incoming SSH connections to 8 in a one minute window". So is this 8 connections to eth0 from any IP, or 8 connections per IP per minute?

#57. Chris on 10 May 2008

ChrisThanks Kevin!

#56. Melvin on 28 November 2007

MelvinHi Kevin,

Very useful, thanks!

#55. Michael on 28 November 2007

MichaelExcellent article, Kevin.

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

Kevin@ Carl: One thing that works on almost every distro is to put it into: /etc/rc.local

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

CarlSo, what do you do when you're running a RH based distro? The /etc/network dir isn't on CentOS, Fedora, RHEL etc. I have no clue how to implement this on one of these servers..

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

AndrewTo have some fun, you can setup a honeypot on the standart port and do counter attacks >:) , since the attacking machine is probably a brute force victim, you can eventually get in (and do some fixing ... muahahaa ...)

#51. Kevin on 23 September 2007

KevinThanks everyone for the useful comments. @ Pete: but what if your server is subject to a coordinated attack with multiple machines on Gigabit. I've seen this happen in real life. And assuming that your password is probably not going to be cracked, does not provide solid security. As machines & connections are getting faster & faster, more combinations can be tried in less time. This is a movement that will not stop, making it more & more likely a brute force attack will succeed. Besides, it's a good way to stop the pollution in your ssh logfiles.

#50. Pete on 22 September 2007

PeteNice article, but I would take issue with you saying that it's just a matter of time before a brute force login attack works. With a half decent password, the length of time it'd take simply makes it unfeasible. Bear in mind that a brute force attack over the network is several orders of magnitude slower than a password cracker such as John (which can typically try tens of thousands of passwords per second).

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

erth64netTo implement in shorewall, use the Rate Limit options in /etc/shorewall/rules

#48. Mukund on 12 September 2007

Mukundsmooch! Thanks a ton. That helped.

#47. Nphyx on 07 September 2007

NphyxAlso, @math and others with the same snipe:
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

NphyxThanks so much for laying that out. I'm a long time PC geek but I'm just trying to get back into linux after a long, long hiatus. I knew where my logs were, I knew I had a problem, and I knew iptables was the solution but figuring out how to use it hasn't been quite as easy as I would have hoped. This little article hit the nail right on the head. Well my problem was actually FTP, but a couple tiny modifications and voila, no more 10,000 entries per day on my FTP server logs. Thanks again!

#45. Chiron on 21 August 2007

ChironThis is great. After reading it I just had a casual look at my auth.log file, and was surprised to see some very concerted brute-force attacks. I made the appropriate entries into iptables (and also finally got around to disabling root login for ssh, something I'd been meaning to do for a long time now...).

#44. math on 11 August 2007

mathif you have moderately good passwords (ie not guessable first try), but requires the attacker to try the whole character space available (some 96 odd chars) we're lookinga t 96^6 attempts for a 6 char password. at 100 tries per second (dos attack!) we're looking at 248 years. or 0.4% chance per year * account. Not per year per account, per year * account, meaning once they fail to break open 'apache' user because there IS no password for apache, they have to spend another 248 years to exhaust the space for 'samba' another account likely to not have a password (at least in debian).

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

DigeratiIn your article at the part where it says "Restore on boot" and it describes where to put it for ubuntu, what do you do for fedora cause it doesnt have an ifup.d dorectory, only /etc/sysconfig/network-scripts
which is loaded with several scripts.
Not sure what to do.

#42. Kevin on 06 August 2007

KevinHi Daniel, I think you could just remove the -i eth0 option. This way you do not specify a network interface so it should work for all your interfaces (LAN + WAN)

#41. Daniel on 06 August 2007

DanielHi Kevin,
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

Zigzo ZLinksThis was a really great article. I'm glad i came across your blog (via digg) thanks!!

#39. Kevin on 03 August 2007

Kevin@ Geog: Correct me if I'm wrong but I believe -m limit rate limits connections to a port globally, without caring about where the connections are coming from, whereas -m recent keeps track of individual IPs.

#38. Geog on 02 August 2007

GeogIs using -m recent better than using -m limit ?
I do this with -m limit. I haven't thought
about -m recent.

#37. Kevin on 02 August 2007

KevinThanks for all the tips you guys!

#36. Jay Fude on 02 August 2007

Jay FudeI Put the iptables in my /etc/init.d/boot.local under OpenSUSE 10.2, and added /usr/ before the path to iptables. Works great and makes my log file happy.

#35. Anon on 02 August 2007

AnonAn alternative is to try ssh-faker (http://www.pkts.ca/ssh-faker.shtml). It will still allow users who know the "faker" password through, but stops the brute force attacks at zero attempts instead of 8 per minute.

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

Thomas Mathiesenossec (http://www.ossec.net/) and denyhosts is similar, and maybe easier to setup for joe.

#33. dany on 02 August 2007

danyI am using pam_abl for like 3 years on many servers. It can autoblacklist users and IP, is simple to configure and fun! And because its based on PAM, it is real system solution
http://www.hexten.net/wiki/index.php/Pam_abl

#32. psychicist on 02 August 2007

psychicistWhy not use asymmetric SSH2 key encryption? I have been using that for years and disable every other login option. You should just remind yourself of replacing your keys regularly.

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

Peter N. M. Hansteenit's even easier to do this with OpenBSD's PF, (available on other BSDs as well), integrated in yor reglar rule set. see eg http://home.nuug.no/~peter/pf/en/bruteforce.html

#30. Erm on 01 August 2007

ErmI like denyhosts, but on top of that I always keep a konsole open with an active view of what's going on with my system.log

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

VinasI prefer this iptables rule. Similar to yours, except it will only allow a maximum of 3 tries in 300 seconds. This effectively filters out about 98% of the scans and automatically turns back on, etc.

#! /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

linuxtravelerVery interesting post.
I didn't know this module!

#27. Asktheadmin on 31 July 2007

AsktheadminGreat information I would love to post this for our readers over @ <a href="http://www.askTheAdmin.com">AskTheAdmin.com</a>

#26. kentborg on 31 July 2007

kentborgMoving sshd to a different port doesn't work as well as you might like. A few years ago I had an account on a machine that was not well maintained and there was an ssh problem that was not patched. The machine was broken into. It was on a non-standard port. It was still broken into.

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

foutrelisHey! My vps has three entries in /etc/network/interfaces. venet0 and two others for the two ips, venet0:0 and venet0:1

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

Lean FuglsangDoes this rule make it possible to do a denial of service attack?

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

ZotterNot bad at all! Another layer to add in!

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

Hyper ViperI've changed the ports my ssh servers run on. It's incredible to see all the attempts on port 22. The one issue that I've run into with this config is I ended up with some issues with Subversion. A little work with my .ssh/config and I was back in business.

#21. Matt on 31 July 2007

MattOr you can edit /etc/ssh/sshd_config

Some interesting things in this file:

Port 2222
... [more] PermitRootLogin no
MaxAuthTries 2
AllowUsers ::YOURUSER::

yep...

#20. Isolder on 31 July 2007

IsolderI'm also a big fan of DenyHosts. It's fast, efficient and can be configured to clear the denied hosts at certain intervals.

#19. DB on 31 July 2007

DBIs there any way to implement this in Shorewall?

#18. SnortSam on 31 July 2007

SnortSamSnortSam - Flexible, per rule blocking specification, including rule dependent blocking time interval.

#17. BobsUrUncle on 31 July 2007

BobsUrUncleNice! Thanks for this; quick and easy, and nothing more to install.

#16. Kevin on 31 July 2007

Kevin@ OMFG: According to WIKI "most commonly an amateur is understood to be someone who does something without pay", so you're probably right ;)

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

OMFGAre you saying that Linux isn't infallible? Now way! It's almost like it's written by amateurs!

#14. Kevin on 31 July 2007

KevinThanks for all of your input. I'm familiar with both fail2ban and denyhosts. They're both awesome solutions, and they may be even easier to set up.

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

CraigHow does this work if I port-forward to a different computer on the "inside"?

/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

Juan SaborDenyHosts is best solution I've seen for Brute Force SSH attacks.

#11. gHOST on 30 July 2007

gHOSTfail2ban....works wonders for brute force attacks.

#10. Reid Ellis on 30 July 2007

Reid EllisHm, I use something similar, but not quite the same:


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

lazy-bit.chif you can afford the "trouble", you can also configure your sshd to use keypairs only.

#8. Casey on 30 July 2007

CaseySo clear and simple. Thanks!

#7. Chuck on 30 July 2007

ChuckLike Azmith said, change your SSH port to something non-default. For example, if you change your SSH port to 52004, you will most likely be safe from 0 day SSH worms. In order to propogate in a reasonable amount of time they will only try 22. In addition, you can add your IP table rules.

#6. gris on 30 July 2007

grisAnother option is to use the DenyHosts script which will automatically put a host in the hosts.deny file after so many failed login attempts.

http://denyhosts.sourceforge.net/

#5. Azmith on 30 July 2007

AzmithOr just change your sshd port to something other than default

#4. Kevin on 30 July 2007

Kevin@ Lukas Meyer: Thank you, I've updated the scripts!

#3. Lukas Meyer on 30 July 2007

Lukas MeyerTwo little improvments to make:
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

KevinHi Bob,

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

Bob ClayThe two iptables rules look identical to me. Shouldn't one be UDP?