Fail2ban
The fail2ban 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.
Features
Jailing
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.
/etc/fail2ban/jail.conf
Example code for SSH jail<syntaxhighlight lang="ini">[DEFAULT] ignoreip = 127.0.0.1 ignoreip = 192.168.100.24 # 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 [ssh-iptables] 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</syntaxhighlight>
jail.d
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.
/etc/fail2ban/jail.d/sshd.conf
syslog-ng & ufw example<syntaxhighlight lang="ini">[ssh-iptables] enabled = true filter = sshd action = ufw[name=SSH, port=ssh, protocol=tcp] logpath = /var/log/messages maxretry = 5 # Override the default of 3</syntaxhighlight>
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.
Actions
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
Installation
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.
Configuration
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:
/etc/fail2ban/jail.d/sshd.conf
rsyslog<syntaxhighlight lang="ini">[sshd] enabled = true</syntaxhighlight>
Or for syslog-ng users:
/etc/fail2ban/jail.d/sshd.conf
syslog-ng<syntaxhighlight lang="ini">[sshd] enabled = true logpath = /var/log/messages</syntaxhighlight>
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
Interacting
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
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: 192.168.100.50 `- Total banned: 2
To get a compact version for all jails, including banned IPs:
root #
fail2ban-client banned
[{'sshd': ['192.168.100.50']}, {'apache-auth': []}]
Troubleshooting
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
Results
=======
Failregex
|- 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)
Ignoreregex
|- Regular expressions:
|
`- Number of matches:
Summary
=======
Addresses found:
[1]
192.168.100.50 (Wed Dec 28 12:46:56 2011)
192.168.100.50 (Wed Dec 28 12:47:00 2011)
192.168.100.50 (Wed Dec 28 12:47:03 2011)
192.168.100.50 (Wed Dec 28 12:47:15 2011)
192.168.100.50 (Wed Dec 28 12:47:18 2011)
192.168.100.50 (Wed Dec 28 12:47:21 2011)
192.168.100.50 (Wed Dec 28 14:23:08 2011)
192.168.100.50 (Wed Dec 28 14:23:12 2011)
192.168.100.50 (Wed Dec 28 14:23:23 2011)
192.168.100.50 (Wed Dec 28 14:23:28 2011)
192.168.100.50 (Wed Dec 28 14:23:31 2011)
192.168.100.50 (Wed Dec 28 14:23:35 2011)
192.168.100.50 (Wed Dec 28 15:15:09 2011)
192.168.100.50 (Wed Dec 28 15:15:12 2011)
192.168.100.50 (Wed Dec 28 15:15:14 2011)
192.168.100.50 (Wed Dec 28 15:15:17 2011)
192.168.100.50 (Wed Dec 28 15:15:20 2011)
192.168.100.50 (Wed Dec 28 15:15:23 2011)
192.168.100.50 (Wed Dec 28 15:21:29 2011)
192.168.100.50 (Wed Dec 28 15:21:32 2011)
192.168.100.50 (Wed Dec 28 15:21:34 2011)
192.168.100.50 (Wed Dec 28 15:21:38 2011)
192.168.100.50 (Wed Dec 28 15:21:41 2011)
192.168.100.50 (Wed Dec 28 15:21:43 2011)
192.168.100.50 (Wed Dec 28 17:36:00 2011)
192.168.100.50 (Wed Dec 28 17:36:03 2011)
192.168.100.50 (Wed Dec 28 17:36:05 2011)
192.168.100.50 (Wed Dec 28 17:36:10 2011)
192.168.100.50 (Wed Dec 28 17:36:13 2011)
192.168.100.50 (Wed Dec 28 17:36:16 2011)
[2]
[3]
[4]
[5]
[6]
[7]
[8]
[9]
[10]
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
information.