From Gentoo Wiki
Jump to:navigation Jump to:search

Fail2ban is a system denying hosts causing multiple authentication errors access to a service.

The service scans log files for patterns of specific repeated attempts (for instance, unsuccessful SSH authentication attempts or high volume GET/POST requests on a web server) and, when detected, automatically creates a firewall or TCP wrappers drop or deny rule to ensure the service availability is not jeopardized.

Although the service supports many services out-of-the-box, it is very versatile in its configuration and can easily be enhanced.



The primary purpose of fail2ban is to jail services. When a service, such as SSHd, is jailed, then fail2ban will continuously look in the log(s) of that service for possible repeated attempts. The moment that a given number (maxretry) of attempts is detected within a particular time window (findtime) then a blocking rule (such as through iptables) is automatically set for a given time period (bantime).

The settings of these jails is done through /etc/fail2ban/jail.conf. By default, fail2ban already provides a nice jail.conf file, but all jails are by default disabled so that the service, when started by the administrator, wouldn't accidentally filter out valid requests.

FILE /etc/fail2ban/jail.confExample code for SSH jail
ignoreip =
ignoreip = # Management network
bantime = 86400 # 1 day (in seconds)
findtime = 300 # 5 minutes (in seconds)
maxretry = 3 # default repeat count

# Jail entry for SSH, using iptables for firewall
enabled = true  # Note that it is by default disabled
filter = sshd
action = iptables[name=SSH, port=ssh, protocol=tcp]
logpath = /var/log/auth.log
maxretry = 5 # Override the default of 3


Jails can and should be broken into individual jail files. Individual jails are easier to sort through, and disable or enable. Fail2ban uses jail.d/*.conf syntax, so moving sshd.conf to sshd.conf.backup will disable the jail.

FILE /etc/fail2ban/jail.d/sshd.confsyslog-ng & ufw example
enabled  = true
filter = sshd
action = ufw[name=SSH, port=ssh, protocol=tcp]
logpath = /var/log/messages
maxretry = 5 # Override the default of 3

Filter expressions

Inside /etc/fail2ban/filter.d various filtering definitions can be created. Generally, these files contain regular expressions that match attempts. When a regular expression is matched on a file, then the counter for that jail and the offending host is increased.


Inside /etc/fail2ban/action.d various action definitions can be created. These files contain commands to execute to ban and unban a given host. By default, rules exist for iptables, nftables, tcpwrappers, shorewall and more.

Log scanning

The fail2ban service supports both file polling or more efficient file modification notifications; when dev-python/pyinotify or app-admin/gamin is installed and the user did not change the backend directive, then pyinotify or gamin will be used, otherwise polling is done. This can of course be configured in /etc/fail2ban/jail.conf.

Using fail2ban


Installing net-analyzer/fail2ban is as simple as:

root #emerge --ask net-analyzer/fail2ban

At the time of writing, no USE flags are to be set (the SELinux USE flag is not selectable and is for use by SELinux-enabled systems). To use gamin, install app-admin/gamin too:

root #emerge --ask app-admin/gamin

To use the sqlite backend, enable the sqlite use flag for dev-lang/python.


To configure fail2ban, go to /etc/fail2ban.

Start with jail.conf as that contains which rules to use (and which services to control) and only override the appropriate settings and enable the rules in jail.d/*.conf. If necessary, create new filters or actions if the included configuration does not satisfy requirements.

For example to enable the default SSH filters for rsyslog users:

FILE /etc/fail2ban/jail.d/sshd.confrsyslog
enabled  = true

Or for syslog-ng users:

FILE /etc/fail2ban/jail.d/sshd.confsyslog-ng
enabled  = true
logpath = /var/log/messages

When finished, start the fail2ban service and to add it to the default runlevel.

root #rc-service fail2ban start
root #rc-update add fail2ban default


As part of the fail2ban service, there is also a fail2ban-client available that can query the fail2ban service.

For instance, to see the running jails:

root #fail2ban-client status
|- Number of jail:    1
`- Jail list:         sshd

To obtain specific information about each jail, such as the list of currently banned addresses, executed filters, etc:

root #fail2ban-client status sshd
Status for the jail: sshd
|- filter
|  |- File list:	/var/log/auth.log 
|  |- Currently failed:	1
|  `- Total failed:	12
`- action
   |- Currently banned:	1
   |  `- IP list: 
   `- Total banned:	2

To get a compact version for all jails, including banned IPs:

root #fail2ban-client banned
[{'sshd': ['']}, {'apache-auth': []}]


When the filters are not working properly, use fail2ban-regex to try them out. Pass it the log file to check and the filter to run, and it will give back what it found.

root #fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/sshd.conf
Running tests

Use regex file : /etc/fail2ban/filter.d/sshd.conf
Use log file   : /var/log/auth.log


|- Regular expressions:
|  [1] ^\s*(?:\S+ )?(?:@vserver_\S+ )?(?:(?:\[\d+\])?:\s+[\[\(]?sshd(?:\(\S+\))?[\]\)]?:?|[\[\(]?sshd(?:\(\S+\))?[\]\)]?:?(?:\[\d+\])?:)?\s*(?:error: PAM: )?Authentication failure for .* from <HOST>\s*$
|  [2] ^\s*(?:\S+ )?(?:@vserver_\S+ )?(?:(?:\[\d+\])?:\s+[\[\(]?sshd(?:\(\S+\))?[\]\)]?:?|[\[\(]?sshd(?:\(\S+\))?[\]\)]?:?(?:\[\d+\])?:)?\s*(?:error: PAM: )?User not known to the underlying authentication module for .* from <HOST>\s*$
|  [3] ^\s*(?:\S+ )?(?:@vserver_\S+ )?(?:(?:\[\d+\])?:\s+[\[\(]?sshd(?:\(\S+\))?[\]\)]?:?|[\[\(]?sshd(?:\(\S+\))?[\]\)]?:?(?:\[\d+\])?:)?\s*Failed (?:password|publickey) for .* from <HOST>(?: port \d*)?(?: ssh\d*)?$
|  [4] ^\s*(?:\S+ )?(?:@vserver_\S+ )?(?:(?:\[\d+\])?:\s+[\[\(]?sshd(?:\(\S+\))?[\]\)]?:?|[\[\(]?sshd(?:\(\S+\))?[\]\)]?:?(?:\[\d+\])?:)?\s*ROOT LOGIN REFUSED.* FROM <HOST>\s*$
|  [5] ^\s*(?:\S+ )?(?:@vserver_\S+ )?(?:(?:\[\d+\])?:\s+[\[\(]?sshd(?:\(\S+\))?[\]\)]?:?|[\[\(]?sshd(?:\(\S+\))?[\]\)]?:?(?:\[\d+\])?:)?\s*[iI](?:llegal|nvalid) user .* from <HOST>\s*$
|  [6] ^\s*(?:\S+ )?(?:@vserver_\S+ )?(?:(?:\[\d+\])?:\s+[\[\(]?sshd(?:\(\S+\))?[\]\)]?:?|[\[\(]?sshd(?:\(\S+\))?[\]\)]?:?(?:\[\d+\])?:)?\s*User \S+ from <HOST> not allowed because not listed in AllowUsers$
|  [7] ^\s*(?:\S+ )?(?:@vserver_\S+ )?(?:(?:\[\d+\])?:\s+[\[\(]?sshd(?:\(\S+\))?[\]\)]?:?|[\[\(]?sshd(?:\(\S+\))?[\]\)]?:?(?:\[\d+\])?:)?\s*authentication failure; logname=\S* uid=\S* euid=\S* tty=\S* ruser=\S* rhost=<HOST>(?:\s+user=.*)?\s*$
|  [8] ^\s*(?:\S+ )?(?:@vserver_\S+ )?(?:(?:\[\d+\])?:\s+[\[\(]?sshd(?:\(\S+\))?[\]\)]?:?|[\[\(]?sshd(?:\(\S+\))?[\]\)]?:?(?:\[\d+\])?:)?\s*refused connect from \S+ \(<HOST>\)\s*$
|  [9] ^\s*(?:\S+ )?(?:@vserver_\S+ )?(?:(?:\[\d+\])?:\s+[\[\(]?sshd(?:\(\S+\))?[\]\)]?:?|[\[\(]?sshd(?:\(\S+\))?[\]\)]?:?(?:\[\d+\])?:)?\s*reverse mapping checking getaddrinfo for .* \[<HOST>\] .* POSSIBLE BREAK-IN ATTEMPT\!\s*
|  [10] ^\s*(?:\S+ )?(?:@vserver_\S+ )?(?:(?:\[\d+\])?:\s+[\[\(]?sshd(?:\(\S+\))?[\]\)]?:?|[\[\(]?sshd(?:\(\S+\))?[\]\)]?:?(?:\[\d+\])?:)?\s*User \S+ from <HOST> not allowed because none of user's groups are listed in AllowGroups$
`- Number of matches:
   [1] 30 match(es)
   [2] 0 match(es)
   [3] 0 match(es)
   [4] 0 match(es)
   [5] 0 match(es)
   [6] 0 match(es)
   [7] 0 match(es)
   [8] 0 match(es)
   [9] 0 match(es)
   [10] 0 match(es)

|- Regular expressions:
`- Number of matches:


Addresses found:
[1] (Wed Dec 28 12:46:56 2011) (Wed Dec 28 12:47:00 2011) (Wed Dec 28 12:47:03 2011) (Wed Dec 28 12:47:15 2011) (Wed Dec 28 12:47:18 2011) (Wed Dec 28 12:47:21 2011) (Wed Dec 28 14:23:08 2011) (Wed Dec 28 14:23:12 2011) (Wed Dec 28 14:23:23 2011) (Wed Dec 28 14:23:28 2011) (Wed Dec 28 14:23:31 2011) (Wed Dec 28 14:23:35 2011) (Wed Dec 28 15:15:09 2011) (Wed Dec 28 15:15:12 2011) (Wed Dec 28 15:15:14 2011) (Wed Dec 28 15:15:17 2011) (Wed Dec 28 15:15:20 2011) (Wed Dec 28 15:15:23 2011) (Wed Dec 28 15:21:29 2011) (Wed Dec 28 15:21:32 2011) (Wed Dec 28 15:21:34 2011) (Wed Dec 28 15:21:38 2011) (Wed Dec 28 15:21:41 2011) (Wed Dec 28 15:21:43 2011) (Wed Dec 28 17:36:00 2011) (Wed Dec 28 17:36:03 2011) (Wed Dec 28 17:36:05 2011) (Wed Dec 28 17:36:10 2011) (Wed Dec 28 17:36:13 2011) (Wed Dec 28 17:36:16 2011)

Date template hits:
2120 hit(s): MONTH Day Hour:Minute:Second
0 hit(s): WEEKDAY MONTH Day Hour:Minute:Second Year
0 hit(s): WEEKDAY MONTH Day Hour:Minute:Second
0 hit(s): Year/Month/Day Hour:Minute:Second
0 hit(s): Day/Month/Year Hour:Minute:Second
0 hit(s): Day/MONTH/Year:Hour:Minute:Second
0 hit(s): Month/Day/Year:Hour:Minute:Second
0 hit(s): Year-Month-Day Hour:Minute:Second
0 hit(s): Day-MONTH-Year Hour:Minute:Second[.Millisecond]
0 hit(s): Day-Month-Year Hour:Minute:Second
0 hit(s): TAI64N
0 hit(s): Epoch
0 hit(s): ISO 8601
0 hit(s): Hour:Minute:Second
0 hit(s): <Month/Day/Year@Hour:Minute:Second>

Success, the total number of match is 30

However, look at the above section 'Running tests' which could contain important