Self-blocking Script Kiddies

For my non-technical family and friends you can tune out as this is a techie computer geek post.

Like many I run a linux machine as a traffic cop at the edge of my network. I prefer to run Secure Shell (SSH) server on its standard port so that I can easily connect to it whenever I need or want to; doing so I understand I open myself up to all kinds of attacks. Over the years I’ve some pretty fierce brute force attempts to guess the password for the SSH. I think I’ve found a fairly simple way to keep the script kiddies out yet still have the server available on demand. There are several solutions out there that provide similar capability, some of which I’ve tried. I personally like this way of doing it better than others because it’s my personal preference because it uses the smallest amount of system resources.

Things you’ll need to implement this on your system are:
1. Certificate based SSH authentication implemented on the server.
2. Almost all linux distributions now come with the iptables and iptables.extensions pre-installed. If they aren’t you’ll need them.
3. You’ll need IPSET to build the blacklist of “bad” IP addresses
4. You’ll need to install xtables-addons to gain access to the TARPIT target, but you could also use the DROP target without it.

I use ubuntu server, so the code you see here works on my machine…

The first thing you need to do is set up certificate based authentication if you haven’t already done so… The page at https://help.ubuntu.com/community/SSH/OpenSSH/Keys explains in detail how to set it up, I will not cover how to actually set it up here. When you have it implemented no amount of password guesses will get them in… With certificate based authentication you’ll connect on the first attempt every time. The rest of this article will help reduce the load on your system of these people trying to brute-force something they can’t get into.

Ubuntu has both iptables and iptables extensions installed by default… so I’m not going to cover their installation.

You will need to install IPSET, so run the following:

sudo apt-get install ipset

Next is xtables-addons. Xtables-addons provides a lot of other capabilities that have not yet been added into iptbles.extensions. To install it you need to run the following:

apt-get install module-assistant
module-assistant auto-install xtables-addons-source

Once this step is complete you can create your firewall script. Somewhere near the beginning of it you need to create the IP set to house blacklisted IP addresses:

ipset -N Blacklist iphash

Next you have to handle traffic from IP addresses that are already on the blacklist. This comes before the section that adds them to the blacklist to keep the logs clean… in other words one IP address to one log entry:

iptables -A INPUT -i p34p1 -p tcp -m set –match-set Blacklist src -j\
REJECT –reject-with tcp-reset

As you can see I’m rejecting traffic with a reset packet as a hint to go away. I could use the TARPIT target and hang them up but each tarpitted connection uses resources on you and all upstream routers. If you turn off connection tracking for your machine, upstream routers still keep track of the connections; to them tarpitted connections are half open until they time out. If traffic isn’t connection oriented (i.e. not TCP) I have this rule in there to handle it:

iptables -A INPUT -i p34p1 -m set –match-set Blacklist src -j DROP

Now for the rules that actually protect the SSH server from brute force connection attempts:

iptables -A INPUT -i p34p1 -p tcp –dport 22 -m state –state NEW -m recent –set/
–name SSH –rsource
iptables -A INPUT -i p34p1 -p tcp –dport 22 -m recent –update –seconds 3600/
–hitcount 8 –rttl –name SSH –rsource -j LOG –log-prefix “SSH-AutoBlacklist: ”
iptables -A INPUT -i p34p1 -p tcp –dport 22 -m recent –update –seconds 3600/
–hitcount 8 –rttl –name SSH –rsource -j SET –add-set Blacklist src
iptables -A INPUT -i p34p1 -p tcp –dport 22 -m recent –update –seconds 3600/
–hitcount 4 –rttl –name SSH –rsource -j DROP
iptables -A INPUT -i p34p1 -p tcp -m tcp –dport 22 -j ACCEPT

Each of the rules above begin with the word “iptables”. The / at the end of the line means the rule continues on the next line. This means that there are just 5 rules to implement.
The first one starts up the recent module and creates a resource name called “SSH”.
The second line creates a log entry if 8 new packets have been received in the last 3600 seconds.
The third line adds the source IP address to a blacklist if 8 packets have been received in the last 3600 seconds.
The fourth line drops all attempts to connect at 4 packets in the last 3600 seconds, I could use the TARPIT target here. I chose not to for a service (Secure Shell) that I use.
The fifth line accepts the packet and passes it to the SSH server.

That’s the nutshell version of it. Basically none of the first four rules fire on the first, second, of third connection attempt. On the fourth attempt it starts dropping connection; on the eighth connection it logs it and adds the source IP address to the blacklist. All subsequent connection attempts are captured by the earlier blacklist rule which causes the firewall to send a RST packet to them which should be a hint to go away.

I’ve added other rules to add services that I don’t run. Even though I don’t run a web server or a mail server or an FTP server I get frequent probes for them. To reduce inbound traffic I’ve added the following:

iptables -A INPUT -i p34p1 -p tcp –dport 21 -j LOG/
–log-prefix “FTP-AutoBlacklist: ”
iptables -A INPUT -i p34p1 -p tcp –dport 21 -j SET/
–add-set Blacklist src
iptables -A INPUT -i p34p1 -p tcp –dport 21 -j TARPIT

The first line adds a line to my log that I had an FTP connection attempt with a log prefix that makes it easy to search the logs.
The second line adds the source address to the blacklisted.
The third line sends the packet to the tarpit.

I send these to the tarpit on their first connection to hang their scripts up to slow them down. One connection doesn’t consume a lot of resources on my machine or any upstream router. The tarpitted connection eventually times out depending on the timeout setting on your machine and upstream routers. On the second and all subsequent connection attempts, the firewall returns an RST packet which should be a hint to go away. You can repeat these three rules for any other port you want logged.

I have the three rules set for port 21 (FTP). I also set them for port 23(Telnet), port 25(Email), port 80 (Web) and port 443(Web). To see what addresses probe for windows computers I have them set for ports that windows keeps open for windows networking (Port 135, Port 139, port 1025 and port 3389).

I do all of this so I have an easy list of IPs that tried to connect to my machine using:

ipset -L

I can also see a more detailed list straight from my syslog by listing the log and piping it to grep like this:

cat /var/log/syslog | grep AutoBlacklist | more

My opinion is this is better than failtoban. With failtoban the connection has to be logged, failtoban reads the log and then implements the ban so it goes higher into the machine. Netfilter works the kernel level… iptables and ipset are userspace tools to modify the kernel level firewall rules which means there is less overhead with this method.

The end result is the script kiddies add themselves to the blacklist by probing commonly exploited ports on your connection. This reduces the amount of work that you as an administrator have to do to actually manage hacking attempts on your system.

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.