Increase your IPv4 security with Fail2Ban and Tinyhoneypot on Debian Jessie

It is a five minutes' exercise to increase security on an IPv4 addressed machine. The purpose of the setup described in this tutorial is to lock out port scanners and malicious port openers for a period of time. This exercise is only tried out and applied on Debian Jessie. During the exercise, each command is committed as root. It is your deal how to get root access. 

Either su -, sudo, console login, etc...

Instruction for lazy beginners: When I represent the bash prompt, just CopyPaste the bold part of the text to your own.

The ingredients

  • The fail2ban software is capable to dynamically handle your firewall rules to lock out bad guys.
  • The tinyhoneypot is capable of listening on a TCP/IP port and logging openers details.
  • The xinetd service starts tinyhoneypot and manages it's listening ports.

Install ingredients: ( Just CopyPaste the bold part of the text )

root@teszt:~# apt-get install tinyhoneypot fail2ban xinetd


In order to make SSH listen on a different port, replace your ssh configuration file with and alternative ssh port:

root@teszt:~# sed -i.orig 's/Port 22/Port 2201/m' /etc/ssh/sshd_config

Your original /etc/ssh/sshd_config config is saved as /etc/ssh/sshd_config.orig

When you restart your SSH service, it will listen on 2201 port (not in 22) now.

root@teszt:~# service ssh restart
root@teszt:~# netstat -lptn | grep ssh
tcp 0 0* LISTEN 4313/sshd
tcp6 0 0 :::2201 :::* LISTEN 4313/sshd

So far so good..

Configure Xinetd to start tinyhoneypot and listen on Port 22 of TCP:

root@teszt:~# cp -v /usr/share/doc/tinyhoneypot/examples/xinetd.d/thp-pasv /etc/xinetd.d/

Edit your /etc/xinetd.d/thp-pasv to like this:

root@teszt:~# cat /etc/xinetd.d/thp-pasv

# default: on
# description: thp-ftpd calls the generic thpsvcs with param "ftp",
#       resulting in an ftpd emulation.

service thp-pasv
        type                    = UNLISTED
        socket_type             = stream
        protocol                = tcp
        port                    = 22
        wait                    = no
        user                    = thpot
        server                  = /usr/sbin/thpot
        server_args             = nullresp
        nice                    = 10
        disable                 = no
        instances               = 1
        per_source              = 1


(RE)Start xinetd with your new settings and make sure it listens on port 22.

root@teszt:~# service xinetd restart
root@teszt:~# netstat -lptn | grep xinetd
tcp 0 0* LISTEN 4567/xinetd

Make sure it is working

Open an ssh connection from an another machine.

attacker@hackerpc:~$ ssh

After a while nothing should happen, interrupt it by [Ctrl + C]

And check log entries on your test machine:

root@teszt:~# cat /var/log/thpot/captures
Feb 29 13:02:10 SID=56D4334221165.nullresp PID=4837 SRC= SPT=47187 ET=00:00:11 BYTES=39

In case everything went well, there should be an entry in your capture log.

Lets tune your Fail2Ban to cooperate with TinyHoneyPot

root@teszt:~# cd /etc/fail2ban/
root@teszt:/etc/fail2ban# cp -v jail.conf jail.local

Never edit your jail.conf!! Make a copy of it as jail.local and ONLY make changes in the .local file!

Find the [ssh] section in your jail.local and modify it depending on [Port 2201] of /etc/ssh/sshd_config


enabled  = true
port     = 2201
filter   = sshd
logpath  = /var/log/auth.log
maxretry = 6

Make and entry in the JAIL section of jail.local:

This will make Fail2Ban to read the log file of tinyhoneypot and get the IPv4 address from it to deny. I recommend to place it after the [ssh] section. It is about the 137th row.


enabled  = true
port     = all
filter   = thpot
logpath  = /var/log/thpot/captures
banaction = iptables-allports
maxretry = 1
findtime = 1800
bantime = 99999

Fail2ban should have a filter in order to know what to deny. There  is a macro which substitute IPv4 address. Create a filter for it:

root@teszt:~# cat /etc/fail2ban/filter.d/thpot.local


failregex = SRC=<HOST>
ignoreregex =

It has been done!

Just a short testing....

root@teszt:~# service fail2ban restart

You should see something similar at the end of /var/log/fail2ban.log

2016-02-29 13:54:06,915 fail2ban.jail   [6102]: INFO    Creating new jail 'thp-ssh'
2016-02-29 13:54:06,915 fail2ban.jail   [6102]: INFO    Jail 'thp-ssh' uses pyinotify
2016-02-29 13:54:06,920 fail2ban.jail   [6102]: INFO    Initiated 'pyinotify' backend
2016-02-29 13:54:06,922 fail2ban.filter [6102]: INFO    Added logfile = /var/log/thpot/captures
2016-02-29 13:54:06,923 fail2ban.filter [6102]: INFO    Set maxRetry = 1
2016-02-29 13:54:06,925 fail2ban.filter [6102]: INFO    Set findtime = 1800
2016-02-29 13:54:06,926 fail2ban.actions[6102]: INFO    Set banTime = 99999
2016-02-29 13:54:06,934 fail2ban.jail   [6102]: INFO    Jail 'ssh' started
2016-02-29 13:54:06,940 fail2ban.jail   [6102]: INFO    Jail 'thp-ssh' started

You can see your custom values from jail.local and fine tune them if needed.

findtime = 1800
bantime = 99999

Have a look at your current iptables rules:

root@teszt:~# iptables-save

# Generated by iptables-save v1.4.21 on Mon Feb 29 14:05:17 2016
:fail2ban-ssh - [0:0]
:fail2ban-thp-ssh - [0:0]
-A INPUT -p tcp -j fail2ban-thp-ssh
-A INPUT -p tcp -m multiport --dports 2201 -j fail2ban-ssh
-A fail2ban-ssh -j RETURN
-A fail2ban-thp-ssh -j RETURN
# Completed on Mon Feb 29 14:05:17 2016

Let's check the deny rule from an another machine:

attacker@hackerpc:~# ssh
attacker@hackerpc:~# ssh
ssh: connect to host port 22: Connection refused

The first action will do nothing. The attacker will probably interrupt it after a while The second action will be refused.

Your iptables rules should look like this by now:

root@teszt:~# iptables-save

# Generated by iptables-save v1.4.21 on Mon Feb 29 14:10:53 2016
:fail2ban-ssh - [0:0]
:fail2ban-thp-ssh - [0:0]
-A INPUT -p tcp -j fail2ban-thp-ssh
-A INPUT -p tcp -m multiport --dports 2201 -j fail2ban-ssh
-A fail2ban-ssh -j RETURN
-A fail2ban-thp-ssh -s -j REJECT --reject-with icmp-port-unreachable
-A fail2ban-thp-ssh -j RETURN
# Completed on Mon Feb 29 14:10:53 2016

The result is: The attacker's PC is REJECTED on each port.

The Postscript

At the time of this HowTo was writing neither Fail2Ban not tinyhoneypot was able to handle IPv6 If you think this Howto is useful, share it! Let your friends know about it.

Share this page:

9 Comment(s)

Add comment


From: nagyorgy

Author's note:Sorry, I have found one mistake I made during the formating.The /etc/fail2ban/filter.d/thpot.local file should be look like this:[Definition]failregex = SRC=<HOST>

From: StoneKany

Hi nagyorgy. I'm currently using Ubuntu 14.04 and followed all steps from your guide. But when I use the command "service fail2ban restart" I'm having the following issue:

ERROR  Failed during configuration: File contains parsing errors: /etc/fail2ban/filter.d/thpot.local

[line  3]: '<HOST>\n'


Do you have a workaround for it?

From: zulli

I had to make a few minor configuration adjustments to get mine to work, please correct me if I am wrong - 

I changed to thpot.local to thpot.conf as a personal preference and here is what I had to use in order to not have fail2ban bark about the ignoreregex not being in the file


failregex = SRC=<HOST>

ignoreregex =

Fail2ban was complaining that the ignoreregex entry was absent in the thpot.conf file when I restarted it. I also had to create my /var/log/thpot/captures file manually with my text editor, fail2ban didn't see it so it was complaining about it when it was restarted.

From: nagyorgy

1,) You are right, that is the correct content of thpot.local!!I will ask site editors to correct my mistake. ( the Fail2Ban recommendation is to use .local files for your custom configurations )First, I made a mistake because <pre> <HOST> </pre> HOST was handled as a HTML tag.AND I accidentally forgot EOF in the file.The EOF came from ideal of creating the file and its content by a single CopyPaste command like this one:

See ->   

2,) The ignoreregex is a good point, thnx3,) The  /var/log/thpot/captures was created during the TinyHoneypot configuration, one section before Fail2BanI ask pardon from everybody about this inconvenience



From: MB.n

What is the really correct look like from /etc/fail2ban/filter.d/thpot.local? Ist it:


failregex = SRC=<HOST>





failregex = SRC=<HOST>

ignoreregex =


when i cat the log of fail2ban, its not create the thp-ssl jail but only warning is this:

2016-10-25 00:55:11,097 fail2ban.jail   [4339]: INFO    Jail 'ssh' started

2016-10-25 00:55:12,141 fail2ban.actions[4339]: WARNING [ssh] Ban

2016-10-25 01:02:27,637 fail2ban.server [4339]: INFO    Stopping all jails

2016-10-25 01:02:27,673 fail2ban.actions[4339]: WARNING [ssh] Unban

2016-10-25 01:02:27,687 fail2ban.jail   [4339]: INFO    Jail 'ssh' stopped

From: MB.n

i checked it for myself and the answer is:


failregex = SRC=<HOST>


ignoreregex =


Anybody know if thp and fail2ban can handle ipv6 now?

From: StoneKany

I'm having the following error: ERROR Failed during configuration: File contains parsing errors: /etc/fail2ban/filter.d/thpot.local

From: Brandon

Is it possible to use this with UFW?    I know UFW is a front-end for IPTABLES, but sometimes they can't work in conjunction.

From: Brandon

Just FYI, I set this up on a brand new server yesterday.   This server hasn't been linked to anything or used yet, I'm just configuring it initially.

And already, this solution has found and blocked approximately 20 IPs.   An excellent solution to find scanners and kill them.   This is likely one of the best security solutions to proactively stop potential hacking attempts.   Great job and thank you!!