3

I'm using a custom filter in fail2ban to search through it's own log and ban an ip after 5 bans from any of the regular filters. I'm using iptables-allports as action for this. All other filters are configured with iptables-multiport.

This is the specific config in jail.conf

[fail2ban]
enabled  = true
filter   = fail2ban
action   = iptables-allports[name=fail2ban]
logpath  = /var/log/fail2ban.log
maxretry = 5
findtime = 604800
bantime  = 2592000

My filter fail2ban.conf looks like this (redundant comments removed)

[Definition]
# Count all bans in the logfile
failregex = fail2ban.actions: WARNING \[(.*)\] Ban <HOST>
# Ignore our own bans, to keep our counts exact.
ignoreregex = fail2ban.actions: WARNING \[fail2ban\] Ban <HOST>

iptables-allports.conf is the default that came with fail2ban 0.8.6-3 for Ubuntu 12.04.2

The problem is, whenever an ip gets banned from one of the regular filters, say sshd, it gets banned for 10 minutes. But the fifth time the same address get's banned, the fail2ban filter is supposed to ban that ip for 30 days, but since it's already banned in the fail2ban-ssh chain it fails.

Maybe the issue is easier to understand if you look at this log

2013-03-19 16:28:34,304 fail2ban.actions: WARNING [ssh] Ban 202.191.128.252
2013-03-19 16:38:34,992 fail2ban.actions: WARNING [ssh] Unban 202.191.128.252
2013-03-19 22:08:58,961 fail2ban.actions: WARNING [ssh] Ban 202.191.128.252
2013-03-19 22:18:59,675 fail2ban.actions: WARNING [ssh] Unban 202.191.128.252
2013-03-20 03:52:25,005 fail2ban.actions: WARNING [ssh] Ban 202.191.128.252
2013-03-20 04:02:25,672 fail2ban.actions: WARNING [ssh] Unban 202.191.128.252
2013-03-20 09:29:51,020 fail2ban.actions: WARNING [ssh] Ban 202.191.128.252
2013-03-20 09:39:51,734 fail2ban.actions: WARNING [ssh] Unban 202.191.128.252
2013-03-20 12:34:01,832 fail2ban.actions: WARNING [ssh] Ban 202.191.128.252
2013-03-20 12:34:03,718 fail2ban.actions: WARNING [fail2ban] 202.191.128.252 already banned
2013-03-20 12:44:02,545 fail2ban.actions: WARNING [ssh] Unban 202.191.128.252

As you can see, fail2ban sees the ip as already banned, even though it's for a different port (or rather: a specific port, 22, instead of the generic "all ports") and thus does nothing.

I'm wondering if, and how, you can make fail2ban ban the ip in the fail2ban-chain, even though it's already banned for ssh?

Any guidance appreciated. Thanks.

  • Maybe you should unban the ip (from the 10mn list) just before you ban it for 30 days... – Ring Ø Mar 20 '13 at 13:20
  • @ring0 that has crossed my mind :) but how would i go about doing that? – Simon Kjellberg Mar 20 '13 at 13:37
  • Don't use the name fail2ban as the section name, resp. don't use a name that starts with the same name as your iptables chain name. – Adrian Zaugg Apr 14 '17 at 19:12
1

While fail2ban creates an iptables chain per service (eg fail2ban-ssh), the check for an existing ban is based on the IP address. A possibility to fix the problem is to make fail2ban unban an IP (ticket) if it is already in the banned-list just before it is going to ban it (again)

These actions happen in the python script located (when installed via apt-get install) in

/usr/share/fail2ban/server

edit the file actions.py, you should see the following code for the __checkban definition

def __checkBan(self):
        ticket = self.jail.getFailTicket()
        if ticket != False:
                aInfo = dict()
                bTicket = BanManager.createBanTicket(ticket)
                aInfo["ip"] = bTicket.getIP()
                aInfo["failures"] = bTicket.getAttempt()
                aInfo["time"] = bTicket.getTime()
                aInfo["matches"] = "".join(bTicket.getMatches())
                if self.__banManager.addBanTicket(bTicket):
                        logSys.warn("[%s] Ban %s" % (self.jail.getName(), aInfo["ip"]))
                        for action in self.__actions:
                                action.execActionBan(aInfo)
                        return True
                else:
                       logSys.warn("[%s] %s already banned" % (self.jail.getName(), aInfo["ip"]))
        return False

modify/replace the definition with

def __checkBan(self):
        ticket = self.jail.getFailTicket()
        if ticket != False:
                aInfo = dict()
                bTicket = BanManager.createBanTicket(ticket)
                aInfo["ip"] = bTicket.getIP()
                aInfo["failures"] = bTicket.getAttempt()
                aInfo["time"] = bTicket.getTime()
                aInfo["matches"] = "".join(bTicket.getMatches())
                # changes from here ...
                if not self.__banManager.addBanTicket(bTicket):
                        logSys.warn("[%s] first unban %s before ban" % (self.jail.getName(), aInfo["ip"]))
                        self.__unBan(ticket)
                        self.__banManager.addBanTicket(bTicket)
                logSys.warn("[%s] Ban %s" % (self.jail.getName(), aInfo["ip"]))
                for action in self.__actions:
                        action.execActionBan(aInfo)
                return True
                # else:
                #       logSys.warn("[%s] %s already banned" % (self.jail.getName(), 
                #                                                                                       aInfo["ip"]))
        #return False

and restart fail2ban (e.g. /etc/init.d/fail2ban restart) while it is probably not necessary...

Note: if you want to 'play around' with this, you can list the firewall (iptables) rules

iptables -L

and delete the rule that was created by fail2ban in order to access and force a "re-ban"

iptables -D fail2ban-ssh xxxx

where xxxx is the number of the rule in that chain from the list iptables -L fail2ban-ssh

  • Wow, perfect! thanks! Though it'd ofc be preferable if this could be done with the custom filters/actions without modifying core files. – Simon Kjellberg Mar 20 '13 at 16:11
  • Maybe there could be a solution using a filter looking for banned n times + unbanned (that would prevent the double banning) – Ring Ø Mar 20 '13 at 16:51
0

if your host behind NAT, then blocking ip in INPUT will not work. you have to choose FORWARD instead.

for example, I'm using Asterisk in Docker, So blocking INPUT will not work. I made jail role like this:

[asterisk]
enabled = true
filter = asterisk
action = iptables-allports[chain=FORWARD, name=asterisk, protocol=all, blocktype=DROP]
logpath = /home/asterisk/logs/messages
bantime = 10800
maxretry = 2

the I can see counting drop packet increases like pic attached.

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.