Firewalling SSH brute force attacks.

September 21, 2011

Anyone who runs their own Linux server knows the annoyance of looking through the log files to see automated SSH brute force attacks trying to find a login to the machine. In the past, I’ve avoided this problem simply by running sshd on a non-traditional port, which makes all the automated scripts that attack port 22 fail.

I recently had to move sshd back to port 22, and I quickly tired of seeing 5k failed login attempts every day.

UPDATE: After some Googling, and after taking into account a lot of good advice from the comments, as well as from John and Smooge, here’s how I’ve rewritten my firewall to protect against brute force ssh attacks.

# set default policies
iptables -P INPUT DROP

# all pre-established clients
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# new inbound ssh, protecting against brute-force attacks
iptables -A INPUT -p tcp -m tcp --dport 22 -m state --state NEW -m recent --set --name SSH
iptables -A INPUT -p tcp -m tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 4 --rttl --name SSH -j DROP
iptables -A INPUT -p tcp -m tcp --dport 22 -m state --state NEW -j ACCEPT

The changes improve efficiency by moving all the RELATED and ESTABLISHED filtering to the beginning of the checks. Also, the order of the checks on the NEW ssh connections have been fixed based on the suggestions in the comments.

The blocked IPs are stored in /proc/net/ipt_recent/SSH.


23 Responses to “Firewalling SSH brute force attacks.”

  1. randy faux Says:

    Could also use fail2ban.

  2. You really saw 5k requests on your box in a day? My machine at home that sits live on a Fiber connection had 477 failed SSH attempts in 3 days!

    I used to worry about this, and then I realized that SSHD already implements a connection limit to one per second per connection. At best a malicious user could attempt 86400 times a day, and that’s really not that much.

    I think a larger risk is bad passwords. I like your solution though, it’s very elegant.

  3. jam Says:

    denyhosts works too, you even get a nice report a the end of the day.


  4. Stephen SMoogen Says:

    Max. Could you do an iptables -nxvL of what you said.. the reason is that the order you have printed would say that the 2nd rule might never be gotten to.

    • JAM Says:

      SMoogen is correct, I’m re-posting the rules with the order fixed and with a small addition to log the attempts:

      -A INPUT -p tcp -m tcp –dport 22 -m recent –update –seconds 60 –hitcount 4 –rttl –name SSH -j LOG
      -A INPUT -p tcp -m tcp –dport 22 -m recent –update –seconds 60 –hitcount 4 –rttl –name SSH -j DROP
      -A INPUT -p tcp -m tcp –dport 22 -m state –state NEW -m recent –set –name SSH -j ACCEPT
      -A INPUT -p tcp -m tcp –dport 22 -m state –state ESTABLISHED,RELATED -j ACCEPT

      • spevack Says:

        Can you explain more about what I had wrong? Thanks!

        • jam Says:

          iptables rule processing works on a line by line basis and both ACCEPT and DROP will stop that process and ACCEPT or DROP the connection. In the original order, connections to SSH were accepted on the first line, the rest were not even looked at.
          In the new version we first check if the connections to SSH have hit the limit, in which case we LOG (note that LOG does not stop the processing), then we do the same check and in this case we DROP the connection when the limits are hit, or let iptables process the next line because limits are OK. The next line deals with brand new SSH connections, otherwise the next line which deals with existing connections is processed.

  5. foo Says:

    Best switch to key-based authentication and disable password-based logins altogether. Then you can implement something like monkeysphere to get easy key revocation too:

  6. iPaulo Says:

    Before these rules you may also want to specifically allow ssh traffic from known IP addreses or ranges such as other servers you operate or from the local networks you run.

    Good post, good comments.

  7. Guest Says:

    My Mom’s PC on AT&T has a modem that uses port 22. I use AllowUsers that only allows one user ID, which itself is 10 characters mixed alpha numeric. I also have /etc/hosts.allow to only accept connections from my ISP which is a very small phone cooperative, 4 counties in rural Wisconsin. There are only 10 hits per day all get dropped before even getting to enter the guess an ID game. If allowed into a guessing game then the hits per day would skyrocket.

  8. bodhizazen Says:

    Small clarification, the rule “–rttl” does not track ip address, rather it tracks time to live and is helpful (potentially) if the intruder changes ip addresses (well, it is better then nothing).

    See: man iptables


    This option must be used in conjunction with one of –rcheck or –update. When used, this will narrow the match to only happen when the address is in the list and the TTL of the current packet matches that of the packet which hit the –set rule. This may be useful if you have problems with people faking their source address in order to DoS you via this module by disallowing others access to your site by sending bogus packets to you.


    Also note your rules give 4 attempt s minute, I would increase “–seconds 60” to “–seconds 600” , or 10 minutes.

    If you use scp or svn over ssh, you will likely need to increase your hit count as each file is a new connection.

  9. Cédric Says:

    This technique, known as “connection throttling”, can be applied to any service (web, mail, etc.) you wish to protect against DoS (and might also help in case of DDoS) 😉

  10. spevack Says:

    Thanks for all the comments. I’ve updated the main post and fixed some of the issues that were pointed out.

  11. Ant Says:

    DenyHosts FTW!

  12. Brad Says:

    Or update ssh to use google two phase authentication..


  13. John Clemens Says:

    May not be suitable for individuals . But for companies, try:

    Uses Two-factor authentication to alter firewall rules
    to allow access to port 22.

  14. […] SSH bağlantılarını Brute Force ataklarına karşı firewall korumasına almak […]

  15. andyr Says:

    If you only allow specific userids to connect and then don’t use any standard account names (real names like mary or joe) then the risks are very low. If you can’t use the great two – factor ideas outlined above, then only permit ssh key authentication and protect the private keys.

  16. JAM Says:

    To get the best of protection, we should implement a holistic approach:
    – use throttling via iptables (avoid denials of service and brute force attacks)
    – use denyhosts (complements iptables)
    – control which users have access to ssh
    – make sure root is not allowed to ssh
    – use two factor / two phase authentication
    – make sure private keys are protected.
    – in some cases only allow certain IP addresses

Comments are closed.