Using IPTables to Prevent SSH Brute Force Attacks

Home/Linux, Security/Using IPTables to Prevent SSH Brute Force Attacks

If you have a server with a world facing ssh server, you’ve probably seen brute force attacks in your logs. Some machine starts hammering your ssh server, trying all sorts of logins (staff, root, a, admin, etc…) over and over and over again.

This is bad on a lot of fronts.

I use two simple iptables rules to block any IP address who has made more than 3 ssh connections or attempted connections within the past 3 minutes. So your would-be brute force attacker, gets three tries, and then is locked out for a minimum of three minutes. However, since 99% of the attacks are run by an automated bot, it will either: give up after the connection is refused multiple times, or it will keep hammering away on the closed door, which keeps the running count of attempted connections in the past 3 minutes over 3, keeping the door closed.

First:

iptables -I INPUT -i eth1 -p tcp -m tcp --dport 22 -m state --state NEW -m recent --set --name DEFAULT --rsource

Then run:

iptables -I INPUT -i eth1 -p tcp -m tcp --dport 22 -m state --state NEW -m recent --update --seconds 180 --hitcount 4 --name DEFAULT --rsource -j DROP

I’d also recommend using the script in my post on blocking IP addresses using iptables to deal with any persistent folks, or people poking too hard on your web site, or other services.

By | 2017-05-18T15:17:31+00:00 May 24th, 2008|Linux, Security|31 Comments

About the Author:

31 Comments

  1. Branitar July 24, 2008 at 12:28 pm - Reply

    Is this an immediate measure or do you also have it in a script somewhere so it is started with your server?

  2. Devon July 24, 2008 at 6:07 pm - Reply

    I save my iptables rules and have them loaded at startup using the commands here:

    http://www.digitalsanctuary.com/tech-blog/debian/how-to-block-an-ip-in-linux.html

    As for the block, it’s just for a few minutes (in case I lock myself out – which I’ve done before), but totally breaks any brute-force attempt, since they never stop trying, and hence stay blocked out until they’ve given up.

    Does that answer your question?

  3. Branitar July 25, 2008 at 2:09 am - Reply

    Ahh I guess I figured it out. To make the rules above permanent I just have to save them to a file (as you did in the script in the other article) and edit the interfaces file to load my rules file.

    Thanks a lot! I’m very new to the iptables business and reading through the manual pages I dint really get how to do the 3 attempts thing. So your blog was kind of a live-safer :)

  4. Andries Louw Wolthuizen August 9, 2008 at 6:26 pm - Reply

    Why would you run SSH on port 22? Running sSH on a other port is a simple solution, that keeps most of the attempts out.

  5. Devon August 9, 2008 at 6:37 pm - Reply

    @Andreis: Good question.

    A few answers:

    1) a different port is a good idea for part of a security solution, but you should still have measures in place to prevent brute force attacks. Port scanning to identify ssh server ports isn’t hard. You might duck a large number of automated scanners, but it won’t do anything for a targeted attack. My solution will. So you should do the above anyhow:)

    2) one of the main reasons I don’t run on a different port myself is convenience. I ssh in from a large number of other servers, and scp files frequently. Having to specify a port every time I do any of that would be a pain.

  6. Tim August 22, 2008 at 12:44 am - Reply

    Thnx this helps me out a lot, I was looking for something like this already.

    @Andries
    Still some clients (like on iphone) don’t support different ports then 22

  7. […] Wired Threat Level has posted an interview with the hacker who recently broke into several high profile twitter accounts, such as Fox News, and Barack Obama. Since we know how much you all love twitter, we thought you might want to learn more about it. Apparently he used a brute force method to get into a member of the support team. The password was “happiness” which was cracked pretty quickly. This might be a good time to review your own strategies to prevent brute force attacks. […]

  8. […] Wired Threat Level has posted an interview with the hacker who recently broke into several high profile twitter accounts, such as Fox News, and Barack Obama. Since we know how much you all love twitter, we thought you might want to learn more about it. Apparently he used a brute force method to get into a member of the support team. The password was “happiness” which was cracked pretty quickly. This might be a good time to review your own strategies to prevent brute force attacks. […]

  9. James January 9, 2009 at 2:54 am - Reply

    Is this not similar (if a little simpler) to the denyhosts service?

    • Devon January 9, 2009 at 4:30 am - Reply

      @James: Yes, it’s a similar approach. However there are a few reasons you might want to consider using the iptables rules instead of the denyhosts service:

      DenyHosts runs periodically (either via cron or as a deamon), and in the FAQ the author recommends running it every 10 minutes. Your server will take a very high number of brute force attempts in 10 minutes. The iptables rule will block after 4 attempts, much more quickly than denyhosts, and hence reduces the chances of a successful brute forcing attempt.

      I don’t like running processes as root, like DenyHosts. The only real advantage of DenyHosts is the new synchronization mode, which would let you block servers that haven’t even attacked you yet, saving your the four attempts the iptables rule would allow. However, running a python script as root, that pulls data from a 3rd party non-SSL server and then uses that data to modify my server’s hosts.deny file. Doubly so when that data is already being collected from other users of this 3rd party service. I’m not sure what prevents a malicious user of the service from submitting perfectly legit IPs or IP ranges and having the synchronization service push that data out to all the other users. I.e. I could submit all Comcast IPs and have them get blocked by users of the service, even though they are legit. Also, with the lack of SSL, I’d worry about the possibility of cache poisoning or DNS poisoning attacks being another vector to poison the data going into the hosts.deny file.

      The hosts.deny file is used for ALL services, not just SSH. This would prevent people with infected PCs from visiting your websites.

      The hosts.deny file is only read by tcpwrappers, and not all programs use it, so if I really did want to block all services, it might not suffice.

      Mostly it comes down to me liking the control that iptables gives me, and being somewhat paranoid:)

      • tx November 9, 2009 at 10:13 am - Reply

        Denyhosts can be run in daemon mode which will actively monitor ssh logins and update hosts.deny immediately. Further it is possible to run the daemon as a non-root user (see http://denyhosts.sourceforge.net/faq.html#3_1). And lastly it is possible to tell denyhosts to block only a specified service instead of all services. Personally, I would rather block all communication from a compromised host.

        • Devon November 9, 2009 at 10:16 am - Reply

          Good to know. It looks like the deamon mode is new-ish. However it defeats the non-root aspect you mention:

          If you are running DenyHosts in daemon mode then yes you must run DenyHosts as root.

  10. questionablemoose March 5, 2009 at 11:05 pm - Reply

    Instead of spending 15 minutes checking auth.log, I now spend about 30 seconds. Works brilliantly as far as I’m concerned. Thanks!

  11. amdrew May 3, 2010 at 10:18 am - Reply

    yea a simple solution, thanks for this great post :)

  12. JD July 1, 2010 at 1:09 pm - Reply

    Thanks, great article!
    How would you go about adding these blocks to a separate log file, say /var/log/iptables.log?

  13. Kevin September 14, 2010 at 6:41 pm - Reply

    What do you think about using a ruby script like this:

    http://github.com/nazar/report-hack-isp

    in tandem with your iptables solution? I see iptables as protecting your server (or mine) and the script being proactive about protecting the web a little more by alerting the ISP in charge. Thoughts?

    • Devon September 16, 2010 at 7:13 am - Reply

      Kevin,

      looks good! Being a better net citizen is always good.

  14. […] Also, rather than using Denyhosts or fail2ban you could use iptables itself to block bad repeated attempts at SSH. […]

  15. […] Also, rather than using Denyhosts or fail2ban you could use iptables itself to block bad repeated attempts at SSH. […]

  16. Mark August 26, 2011 at 8:47 am - Reply

    Thanks for this. I didn’t even realize I had a problem until my /var volume filled up due to a tremendously large /var/log/btmp file. Combining this with blocking a few frequent ip addresses, and the problem seems to be under control.

  17. ZenData September 29, 2011 at 12:18 pm - Reply

    Thanks … saved alot of time ….

  18. computer_freak_8 July 1, 2012 at 9:08 am - Reply

    Question:
    So, say I’m having a bad day, and can’t remember my password. I try it five times in one minute, all failing to be correct. Am I locked out from whatever IP I’m at until I remove myself from the IPTables block list, or will it let me in if I get it correct after waiting a couple minutes?

    • Devon July 1, 2012 at 1:43 pm - Reply

      Just wait more than 3 minutes without trying to login, then you should be fine.

      • computer_freak_8 July 2, 2012 at 10:36 am - Reply

        Okay, cool, thanks! I just tried it, though, and it never locks me out to start with. I intentionally put in a wrong password five times in a row (all within about a minute), and it let me in on try number six (even though I didn’t wait at all for it).

        • computer_freak_8 July 2, 2012 at 10:40 am - Reply

          Oh, hey, it does lock me out… is just let me in once before locking me out. Interesting.

  19. alow November 4, 2012 at 12:13 am - Reply

    Thanks for this post.

    I was trying to find a way to view the ips that are currently in the block list, however there doesn’t seem to be an iptables command that I could find. The ‘DEFAULT’ list referenced in the rules seems to be located here though: /proc/net/xt_recent/DEFAULT; I’m not sure if you know of a better way?

    • Devon November 4, 2012 at 11:35 am - Reply

      Alow,

      I’m not sure. I’ve switched to using CSF to manage my IPTables rules. It has handy commands to see the list of temp or perm blocked IPs, etc…

      http://configserver.com/cp/csf.html

      Devon

    • Nick Coleman January 16, 2013 at 2:23 am - Reply

      You can set up another chain and let it do LOG and DROP. The log entries are in syslog and dmesg. If you have a smart logger (Debian can use rsyslog), you can specify those entries to go into their own file such as iptables.log.

      Google for “iptables ssh log”, there are plenty of examples. They follow the same principle as here with a bit extra for the logging.

  20. nuri huri December 27, 2012 at 6:46 am - Reply

    on first command i get error “iptables: No chain/target/match by that name.”
    pls advice.

  21. RC March 28, 2013 at 5:45 am - Reply

    I cannot get this to work – with just these two rules (the first of which does not specify ACCEPT), I cannot connect over SSH at all. If I add the ACCEPT target to the first rule, I can still bomb my server over and over and the DROP rule never comes into effect.

    • Devon March 28, 2013 at 5:56 am - Reply

      The first rule shouldn’t have an Accept. You’ll need to have port 22 opened on your FW already. That rule is to start tracking SSH connections.

Leave A Comment