Block SSH Cracking Bot-Nets with Netfilter

2 Jan 2009

A few weeks ago, I was looking through some Netfilter documentation, just poking around, looking at some modules I’ve never seen/played-with/hear-of and I came across the recent module. I decided to try it out on one of my servers that gets anywhere from zero (0) to tens of thousands of crack attempts via SSH per day and see if I could weed out some of these bot-nets. It also occurs to me that this could help fight email SPAM-bots, too.

Of course, it’s very important to have good, strong password security practices. If you have poor passwords, none of this will matter, as you’ve probably already been compromised whether you know it or not. This means that all users have to have strong passwords. Techniques for helping users to create and use strong passwords are beyond the scope of this article, but I will write about these things in the near future.

Here’s the configuration that I put into place. I’m showing this as the the iptables commands that you would run on the command line, adapt to however you persist your Netfilter configuration. Also note that these lines should replace anything that you now have in there for SSH. I’m also including the additional ESTABLISHED,RELATED rule here for completeness:

# iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# iptables -A INPUT -i $OUTSIDE_INTERFACE -p tcp --sport $UNPRIV_PORTS --dport 22 -m state --state NEW -m recent --update --seconds 10 -j REJECT --reject-with icmp-host-prohibited
# iptables -A INPUT -i $OUTSIDE_INTERFACE -p tcp --sport $UNPRIV_PORTS --dport 22 -m state --state NEW -m recent --set -j ACCEPT

These three rules mean:

  1. Accept traffic for “conversations” that are already in progress. This rule works for traffic in both directions and will handle everything in the ongoing connection.
  2. If an IP packet matches these criterion:
    1. -A INPUT -i $OUTSIDE_INTERFACE” — coming in on the Internet connetion (I create a variable with the value “eth0” or whatever it is and use that in my firewalling scripts);
    2. -p tcp” — carry TCP (for Layer 4) in the IP packet payload;
    3. --sport $UNPRIV_PORTS” — coming from an unprivileged TCP port (legitmate clients should only come from source ports 1024 through 65535, inclusive);
    4. --dport 22 — destined for TCP port 22;
    5. -m state --state” — the state module doesn’t have a record of this packet as being part of an existing connection;;
    6. -m recent --update --seconds 10” — the update module has a record of another connection attempt matching this one within the past 10 seconds.

    Take these actions:

    1. -j REJECT” — throw the packet away;
    2. --reject-with icmp-host-prohibited” — return an ICMP host-prohibited response to the client who tried to initiate this connection.
  3. The last rule is essentially the same as the second, except for:
    1. -m recent --set” — make a note of the time that this connection attempt occurs at;
    2. -j ACCEPT” — if all criterion match, accept the packet (which will stop further rule processing here, BTW).

Basically, what we’re trying to do here is to limit the number of failed connection attempts that are allowed.

Let’s say that human being tries to connect via ssh and they don’t have an account or the mis-type their password several times to the point where sshd cuts off the connection, so they re-run their ssh command to try again. It will probably work and let them in, as it probably took them longer than 10 seconds from the first packet of the first TCP connection until the first packet of the next TCP connection.

However, the cracker-bot-nets don’t work like humans. They automate the process of trying to connect as fast as they can, so they will try only 1 or maybe as many as 3 or 4 passwords before closing the TCP connection and starting another. Since they don’t have to be as slow as people, they’ll usually be coming back again in under the 10 seconds. Most of them actually try to establish multiple connections (2-20ish at a time) in order to try more passwords.

Once the crack-bot starts seeing TCP connection failures, they usually skip your IP and go on to try and find softer targets. If they can’t connect to SSH, then why bother wasting time trying.

After setting up this configuration and letting it run for a week, I can report that it works marvelously. I’m getting under 10 break-in attempts per day, now. If you’re going to have SSH visible to the world (and why shouldn’t you?), then I would recommend adopting these Netfilter rules in your firewall configuration.



Leave a comment

You can use these tags : <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>