List based permanent bans with fail2ban

Today I post something about the nice little tool fail2ban. As you probably know, fail2ban can be used to block those annoying brute force attacks against your servers. Other than the also popular and useful tool DenyHosts it allows the protection of other services than SSH as well (e.g. HTML login pages served by Apache). The working mechanism also differs from that of DenyHosts, as fail2ban uses iptables instead of the BSD style hosts.deny file to block annoying brute forcers. Installation is quite simple, on Debian for example, just install it through apt and you’re good to go even with the default config.

One thing that I was missing, was the option to ban IPs forever. You can basically do this by setting bantime to a negative value, but as soon as you reload your iptables rules (e.g. by restarting the fail2ban service or the whole system) the entries for the permanently banned IPs are gone.
To overcome this issue, I did some minor changes to the actions fail2ban executes on start-up and on banning.

IMPORTANT: I strongly advise you, to be careful while playing around with automated banning tools, especially if you can’t reach your server physically. Make sure, that you have something useful set in the ignoreip option under the [DEFAULT] jail (your current IP address) to not accidentally lock you out of the system (really nasty with permanent banning active…)

  1. First, check the banaction currently used (you need that, to modify the correct actionfile afterwards)

    banaction = iptables-multiport
  2. Open up the corresponding actionfile and modify according to the sample below (changes are under the # Persistent banning of IPs comment)

    actionstart = iptables -N fail2ban-<name>
                  iptables -A fail2ban-<name> -j RETURN
                  iptables -I INPUT -p <protocol> -m multiport --dports <port> -j fail2ban-<name>
                  # Persistent banning of IPs
                  cat /etc/fail2ban/ip.blacklist | while read IP; do iptables -I fail2ban-<name> 1 -s $IP -j DROP; done
    actionban = iptables -I fail2ban-<name> 1 -s <ip> -j DROP
                # Persistent banning of IPs
                echo '<ip>' >> /etc/fail2ban/ip.blacklist
  3. Your blacklist should look something like this (one IP per line, of course you can add IPs manually)

  4. Restart fail2ban to make the changes active

Now, what happens is that each time fail2ban starts, it loops through your ip.blacklist and blocks the IPs in there. If fail2ban blocks a new IP, it will automatically append it to the blacklist.


The following config adds some nice features that were missing in the example above:

  • No duplicate iptables rules (@Lin: might be interesting for you)
  • Jail specific blocking rules (similar to Dr. Tyrell’s and samuelE’s suggestions in the comments)
  • Reporting offender IPs to


# Fail2Ban configuration file
# Author: Cyril Jaquier
# Modified by Yaroslav Halchenko for multiport banning and Lukas Camenzind for persistent banning 
# Option:  actionstart
# Notes.:  command executed once at the start of Fail2Ban.
# Values:  CMD
actionstart = iptables -N fail2ban-<name>
              iptables -A fail2ban-<name> -j RETURN
              iptables -I INPUT -p <protocol> -m multiport --dports <port> -j fail2ban-<name>
              # Load local list of offenders
              if [ -f /etc/fail2ban/ip.blacklist ]; then cat /etc/fail2ban/ip.blacklist | grep -e <name>$ | cut -d "," -s -f 1 | while read IP; do iptables -I fail2ban-<name> 1 -s $IP -j DROP; done; fi
# Option:  actionstop
# Notes.:  command executed once at the end of Fail2Ban
# Values:  CMD
actionstop = iptables -D INPUT -p <protocol> -m multiport --dports <port> -j fail2ban-<name>
             iptables -F fail2ban-<name>
             iptables -X fail2ban-<name>
# Option:  actioncheck
# Notes.:  command executed once before each actionban command
# Values:  CMD
actioncheck = iptables -n -L INPUT | grep -q fail2ban-<name>
# Option:  actionban
# Notes.:  command executed when banning an IP. Take care that the
#          command is executed with Fail2Ban user rights.
# Tags:    <ip>  IP address
#          <failures>  number of failures
#          <time>  unix timestamp of the ban time
# Values:  CMD
actionban = if ! iptables -C fail2ban-<name> -s <ip> -j DROP; then iptables -I fail2ban-<name> 1 -s <ip> -j DROP; fi
            # Add offenders to local blacklist, if not already there
            if ! grep -Fxq '<ip>,<name>' /etc/fail2ban/ip.blacklist; then echo '<ip>,<name>' >> /etc/fail2ban/ip.blacklist; fi
            # Report offenders to
            wget -q -O /dev/null<name>/<ip>
# Option:  actionunban
# Notes.:  command executed when unbanning an IP. Take care that the
#          command is executed with Fail2Ban user rights.
# Tags:    <ip>  IP address
#          <failures>  number of failures
#          <time>  unix timestamp of the ban time
# Values:  CMD
actionunban = iptables -D fail2ban-<name> -s <ip> -j DROP
              # Disabled clearing out entry from ip.blacklist (somehow happens after each stop of fail2ban)
              # sed --in-place '/<ip>,<name>/d' /etc/fail2ban/ip.blacklist
# Defaut name of the chain
name = default
# Option:  port
# Notes.:  specifies port to monitor
# Values:  [ NUM | STRING ]  Default:
port = ssh
# Option:  protocol
# Notes.:  internally used by config reader for interpolations.
# Values:  [ tcp | udp | icmp | all ] Default: tcp

Monitoring a remote network interface with tcpdump and Wireshark

In this small how-to, I’ll show how to capture network traffic from a remote system to analyze it using Wireshark.

All you need is tcpdump on the remote machine, where you want to dump the network traffic off and Wireshark on the computer, you want to use to look at the packets flying around.
I use this setup for checking, whats going on on my IPcop firewall.

First, you need to prepare a named pipe on you monitoring station:

mkfifo /tmp/pipe

After this, we build up the connection to the remote system, issue the tcpdump command there and direct all outputs to the pipe:

ssh root@ "tcpdump -i eth0 -s 0 -U -w - not port 22" > /tmp/pipe

Now switch to another console and start Wireshark, listening to our newly created pipe:

wireshark -k -i /tmp/pipe

After Wireshark has started, the ssh console will ask for roots password. After you entered it, you will see the packets getting listed in Wiresharks main screen.

Used tcpdump options

  • -i eth0 specifies the interface to capture from (change to your needs)
  • -s 0 sets the packet snapshot lenght it to the default of 65535, for backwards compatibility with recent older versions of tcpdump
  • -U writes each incoming packet to the file (or std. out) immediately, instead of waiting until the buffer has filled
  • -w – writes to standard output
  • not port 22 keeps tcpdump from returning the traffic we create with our ssh connection

Further info

Detecting rogue WLANs with Kismet

In a corporate environment, where you have several IT- security related regulations, it is critical to know what kind of wireless networks are in range of your facilities to avoid the bypassing of corporate security infrastructure (such as proxies, firewalls…)

This is where Kismet comes into play and assists you in finding rogue wireless LANs, using the monitor mode of your WLAN card.

You can get the software here:
Kismet is open-source and also included in several security related linux distros.

The usage is quite simple. Just press “h” while the program runs to display a list of available keyboard shortcuts.

(taken from

  • Ethereal/Tcpdump compatible data logging
  • Airsnort compatible weak-iv packet logging
  • Network IP range detection
  • Built-in channel hopping and multicard split channel hopping
  • Hidden network SSID decloaking

Here are some screenshots of Kismet in action

Hint (as fas as I know while using it under Ubuntu 8.10):
After closing the program, you might have to get your WLAN card back to managed mode.

  • ifconfig ethXX down
  • iwconfig ethXX mode managed
  • ifconfig ethXX up