Gentoo Wiki



SSH Basics

Tips & Tricks

Other Gentoo-wiki SSH



Fail2Ban scans log files like /var/log/pwdfail or /var/log/apache/error_log and bans IP that makes too many password failures. It updates firewall rules or /etc/hosts.deny to reject the IP address.

Note: The version of fail2ban used in this article is 0.8.0-r1. The steps listed below might not apply to other versions.

Installing the software

You need to enable threads in the python package. Either in make.conf or package.use before emerge.

echo "dev-lang/python threads" >> /etc/portage/package.use 
emerge -avN python fail2ban

You also have to emerge iptables, since that is what fail2ban normally uses to ban IP addresses. See HOWTO Iptables for newbies. If you don't want to use iptables, you can ban using TCP wrappers via the file /etc/hosts.deny.

Enable the SSH Jail

By default, all protocols in fail2ban are disabled. To enable the ssh jail, edit the file /etc/fail2ban/jail.conf and scroll to the section [ssh-iptables] and change the line that says:

enabled  = false


enabled  = true

Fixing SSH Logging with syslog-ng

The default /etc/fail2ban/jail.conf file looks at /var/log/sshd.log for SSH messages. With my stock Gentoo configuration, the SSH messages are written to /var/log/messages by default. We need to edit the /etc/fail2ban/jail.conf file.

vi /etc/fail2ban/jail.conf

Scroll to section "[ssh-iptables]" and enable it and find the line that says:

logpath = /var/log/sshd.log

and change it to:

logpath = /var/log/messages
Note: I had to change the logpath to /var/log/auth.log

If you are using syslog-ng then you need to find out where the authlog file is set in /etc/syslog-ng/syslog-ng.conf. If you don't use syslog-ng, you'll need to figure out where the sshd logs are stored and use that file instead. For example, metalog logs ssh messages to /var/log/sshd/current by default. So, if you use metalog you will want to change the line to:

logpath = /var/log/sshd/current

In the syslog-ng wiki page it is set auth.log, so you will want to change the line to:

logpath = /var/log/auth.log

And don't forget to add/change:


in your sshd_config. Else, password failures are not logged correctly.

Adding courierimap and courierpop3

To add imap and pop3 support add the following lines to the end of /etc/fail2ban/jail.conf file:


enabled  = true
filter   = courierlogin
backend  = polling
action   = iptables[name=courierpop3, port=pop3, protocol=tcp]
           mail-whois[name=courierpop3, dest=root@localhost]
logpath  = /var/log/maillog
maxretry = 5


enabled  = true
filter   = courierlogin
backend  = polling
action   = iptables[name=courierimap, port=imap, protocol=tcp]
           mail-whois[name=courierimap, dest=root@localhost]
logpath  = /var/log/maillog
maxretry = 5

again you need to make sure that the logpath is the correct file for your system. In my system where I use syslog-ng mail log is /var/log/maillog. It might be different for your system. Check your syslog-ng config file.

Don't forget to emerge whois if you use mail-whois action. You also need to emerge mail-client/mailx to get the /bin/mail client working:

emerge -av mailx whois

Using TCP wrappers instead of iptables

If you don't want to use iptables to ban IP addresses, fail2ban also supports TCP wrappers with the action hostsdeny. Here's an example for SSH:


enabled     = true
filter      = sshd
action      = hostsdeny
              mail-whois[name=SSH, dest=root@localhost]
logpath     = /var/log/auth.log
Note: Make sure that /etc/hosts.deny is readable by all daemons utilizing the file. If the file didn't exist before, fail2ban creates it with mode 600, owner root. Change the mode to 644 to avoid problems. E.g.: The pop3 and imap daemons from cyrus-imapd (running under uid "cyrus") drop ALL connections if /etc/hosts.deny exists but is not readable.

Finishing Up

Let's get fail2ban running.

root@chardonnay ~
# /etc/init.d/fail2ban start
* Starting fail2ban
...                                                            [ ok ]

Add it to the default runlevel.

root@chardonnay ~
# rc-update add fail2ban default
* fail2ban added to runlevel default

Check to make sure it is working.

root@chardonnay ~
# ps -ef|grep fail2ban
root     20759     1  1 21:51 ?        00:00:01 /usr/bin/python
/usr/bin/fail2ban -b -v

Look at iptables in order to see whether we have a fail2ban rule.

root@chardonnay ~
# iptables --list |grep fail2ban
fail2ban-SSH  tcp  --  anywhere             anywhere            tcp dpt:ssh
Chain fail2ban-SSH (1 references)

Check the log file.

root@chardonnay ~
# tail /var/log/fail2ban.log
2007-05-04 21:51:22,682 WARNING: Verbose level is 1
2007-05-04 21:51:22,684 INFO: Fail2Ban v0.6.2 is running

So far so good. Now, we can sit and wait for a script kiddie or other nefarious bloke to stroll on by. Or, if you have an extra machine that you don't feel too bad about blocking you can spring the trap yourself.

From a remote host (make sure it's not your current laptop, but some other host that you don't mind banning for a few minutes) do this:

merlot ~ # ssh blah@chardonnay

Now, on the fail2ban host, check the log file

root@chardonnay /tmp/fail2ban-0.6.2/config
# tail -f /var/log/fail2ban.log
2007-05-04 21:51:22,682 WARNING: Verbose level is 1
2007-05-04 21:51:22,684 INFO: Fail2Ban v0.6.2 is running
2007-05-04 21:56:31,652 INFO: SSH: has 5 login failure(s).
2007-05-04 21:56:31,652 WARNING: SSH: Ban (600 s)

And, check iptables again

# iptables --list |grep -B5 -A5 fail
Chain INPUT (policy DROP)
target     prot opt source               destination
fail2ban-SSH  tcp  --  anywhere             anywhere            tcp dpt:ssh
ACCEPT     all  --  anywhere             anywhere
eth1_in    all  --  anywhere             anywhere
eth0_in    all  --  anywhere             anywhere
vmnet8_in  all  --  anywhere             anywhere
Reject     all  --  anywhere             anywhere
smurfs     all  --  anywhere             anywhere            state
INVALID,NEW policy match dir in pol none
ACCEPT     udp  --  anywhere             anywhere            udp
tcpflags   tcp  --  anywhere             anywhere            policy
match dir in pol none
net2fw     all  --  anywhere             anywhere            policy
match dir in pol none

Chain fail2ban-SSH (1 references)
target     prot opt source               destination
DROP       all  -- anywhere
RETURN     all  --  anywhere             anywhere

Chain fw2loc (3 references)

Notice the "DROP" rule in the fail2ban-SSH chain has the blocked host

At this point, it's time to celebrate. You've given yourself an extra layer of protection. You should crack open your favorite bottle of vino to mark the occasion.


If fail2ban does not start correctly after a system crash or power loss, check to see whether the socket file still exists:

# ls /tmp/fail2ban.sock

If it does, remove it manually:

# rm /tmp/fail2ban.sock
# /etc/init.d/fail2ban start
* Starting fail2ban ...            [ ok ]

You can add the following to /etc/conf.d/fail2ban to prevent it from happening again.


The -x option will force fail2ban to overwrite the current stale socket.

If fail2ban does not work with ssh, check whether IP-Addresses or DNS-Names are logged. You may need to set UseDNS = no in /etc/ssh/sshd.conf (and restart sshd).

Retrieved from ""

Last modified: Sat, 27 Sep 2008 07:56:00 +0000 Hits: 13,782