Friday, July 25, 2014

fail2ban with Shorewall

When it came to blacklisting attackers trying to brute-force my services, like SSH, my go-to package has always been DenyHosts. However, issues such as recent vulnerabilities and most notably, its removal from the default repositories for Ubuntu 14.04 LTS caused me to finally switch to fail2ban. The biggest advantage fail2ban provides over DenyHosts is that it is more flexible in its actions and types of services it can monitor (DenyHosts only supports services using TCP wrappers).


Install the fail2ban package:

root@localhost:~# aptitude -yvV install fail2ban

After installation, the fail2ban service will automatically be started:

root@localhost:/etc/fail2ban# ps aux | grep [f]ail2ban
root     11232  0.0  1.8 268164  9360 ?        Sl   02:47   0:00 /usr/bin/python /usr/bin/fail2ban-server -b -s /var/run/fail2ban/fail2ban.sock -p /var/run/fail2ban/

root@localhost:/etc/fail2ban# service fail2ban status
 * Status of authentication failure monitor
 *  fail2ban is running


First, make a copy of the /etc/fail2ban/jail.conf file as /etc/fail2ban/jail.local, as per

Every .conf file can be overridden with a file named .local. The .conf file is read first, then .local, with later settings overriding earlier ones. Thus, a .local file doesn't have to include everything in the corresponding .conf file, only those settings that you wish to override. Modifications should take place in the .local and not in the .conf. This avoids merging problem when upgrading.

root@localhost:/etc/fail2ban# cp -v jail.conf jail.local
‘jail.conf’ -> ‘jail.local’

By default fail2ban uses iptables to control its default banning actions. Luckily using Shorewall is as simple as changing a single line in the /etc/fail2ban/jail.local configuration file.



# Default banning action (e.g. iptables, iptables-new,
# iptables-multiport, shorewall, etc) It is used to define
# action_* variables. Can be overridden globally or per
# section within jail.local file
#banaction = iptables-multiport
banaction = shorewall

The /etc/fail2ban/action.d/shorewall.conf configuration file comments explains this in more detail.

All files in the /etc/fail2ban/action.d/ drop configuration directory control actions to an accompanying service. For example, action.d/ipfw.conf controls how fail2ban tells ipfw, used in FreeBSD systems, what command to run to ban an offending host. Likewise, action.d/shorewall.conf controls what commands are run by shorewall in order to ban an offender.

In /etc/fail2ban/action.d/shorewall.conf the important directives to pay attention to for our setup are actionban, actionunban, and blocktype:

# Option:  actionban
# Notes.:  command executed when banning an IP. Take care that the
#          command is executed with Fail2Ban user rights.
# Tags:    See jail.conf(5) man page
# Values:  CMD
actionban = shorewall <blocktype> <ip>

# Option:  actionunban
# Notes.:  command executed when unbanning an IP. Take care that the
#          command is executed with Fail2Ban user rights.
# Tags:    See jail.conf(5) man page
# Values:  CMD
actionunban = shorewall allow <ip>


# Option:  blocktype
# Note:    This is what the action does with rules.
#          See man page of shorewall for options that include drop, logdrop, reject, or logreject
# Values:  STRING
#blocktype = reject
blocktype = drop
  • To reiterate, when fail2ban bans a host, the command shorewall drop <offending IP address> will be run.

In the above configuration I changed the blocktype to drop rather than reject. Rather than getting an ICMP destination unreachable response from my server when attackers are brute-forcing my services like SSH after they have been banned, drop will cause their connections to timeout instead.

Also, shorewall needs to be updated to handle the banning action correctly. By default, it will only blacklist hosts part of a new TCP connection, but not already existing or established connections.



Restart the fail2ban and shorewall services:

root@localhost:/etc/fail2ban# service fail2ban restart
 * Restarting authentication failure monitor fail2ban                         [ OK ]

root@localhost:/etc/shorewall# service shorewall restart
Restarting "Shorewall firewall": done.

Seeing it in action

After leaving fail2ban running for a couple hours, you are inevitably going to get some banned hosts. You can see that fail2ban is working correctly by checking the /var/log/fail2ban.log log file. Here's an example of some IPs that were banned:

2014-07-23 19:58:16,068 fail2ban.actions: WARNING [ssh] Ban
2014-07-23 20:08:16,818 fail2ban.actions: WARNING [ssh] Unban
2014-07-23 20:46:02,506 fail2ban.actions: WARNING [ssh] Ban
2014-07-23 20:56:03,249 fail2ban.actions: WARNING [ssh] Unban
  • Note the hosts were unbanned after 10 minutes, which is the default timer.
  • To increase the ban time, change the bantime value in the /etc/fail2ban/jail.local configuration file.

To verify that fail2ban did indeed pass the IPs to shorewall use the shorewall show dynamic command:

root@localhost:/etc/fail2ban# shorewall show dynamic
Shorewall Chain dynamic at localhost - Fri Jul 25 07:21:26 EDT 2014

Counters reset Wed Jul 23 03:07:05 EDT 2014

Chain dynamic (4 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 DROP       all  --  *      *           
    0     0 DROP       all  --  *      *           
    0     0 DROP       all  --  *      *           
    0     0 DROP       all  --  *      *           
    0     0 DROP       all  --  *      *           
    0     0 DROP       all  --  *      *           
    0     0 DROP       all  --  *      *           
    0     0 DROP       all  --  *      *  



  1. Hello there! Thanks for this info, I was trying to work out how come fail2ban and shorewall were breaking each other when restarting.
    Now both are running nicely.

    But I have one question, I'm not seeing any banned hosts in my /var/log/fail2ban.log file after a few hours.

    fail2ban-client status
    |- Number of jail: 0
    `- Jail list:

    when I was using iptables I specified

    enabled = true

    but if I manually add that into the new jail.local (cp of jail.conf) fail2ban service then fails to start.
    how am I going to specify what services to enable?

    this isn't clear in your directions.

    Thanks again :)

    1. To answer my own question, I finally found the issue... I didn't have a shorewall.conf file so I created it off the content you supplied, but because I was missing the other parts of the file it was failing, once I found an example online and used the full file it all worked... might be useful to others

  2. This comment has been removed by the author.