A tarpit (also known as Teergrube, the German word for tarpit (German pronunciation: [ˈteːɐ̯ˌɡʁuːbə])) is a service on a computer system (usually a server) that purposely delays incoming connections.
I have some time been thinking that to make life slightly harder for all the ssh scanning bots out there, one should make a SSH tarpit. As outlined in the wikipedia article this is not a new idea, but I still like to investigate the idea of it even if there are clear downsides and risks as outlined in this stack overflow answer. That answer is related to the linux iptables TARPIT extension, which is on my todo to investigate further.
Anyways, my solution relies only on iptables and tc, which should be available on most linux distributions so I believe.
Caution: As this solution just slows down the returning data it will keep a TCP connection open and will probably make your server suspectible to multiple attacks and problems which you did not have before. Please read the previously linked Stack Overflow post for more discussion and don’t use this on any important server.
Still here? Then let’s get started.
First thing you should do, is either set up a separate SSH server or make OpenSSH listen to both port 22 and another port. If you apply this tarpit on your main ssh port with no alternative way to interface with the server you will have a bad time.
After we have our backup port, we create a iptables rule which marks traffic to port 22
iptables -A OUTPUT -t mangle -p tcp --sport 22 -j MARK --set-mark 10
Then create a qdisc for eth0 and set it to use htb.
tc qdisc add dev eth0 root handle 1: htb
For more information on tc, I recommend this guide on linux.com
Then add a default rule which allows really fast traffic, this is our default fallback rule for all traffic which is not caught by the mark
tc class add dev eth0 parent 1: classid 1:0 htb rate 1Gbps
Then a slow rule
tc class add dev eth0 parent 1: classid 1:5 htb rate 100bps prio 1
and finally a filter which catches the traffic marked with mark 10 and puts it in flow 5
tc filter add dev eth0 parent 1:0 prio 1 protocol ip handle 10 fw flowid 5
Congratulations, hopefully if you try to ssh to port 22 it will work, but very slowly.
If you want to inspect the class and how it’s doing, you can use
tc -s -d class show dev eth0
The next level I would like to do is to implement a fake ssh server, which implements a randomly broken protocol. The goal being to try to crash whatever is scanning the server by presenting it with almost correct data, preferably also at a really slow pace to make sure it takes a long time to crash.