Fail2ban: an enemy of script-kiddies
April 29th, 2007 edited by anaI bet there is only a little part of auth.log-aware GNU/Linux users, who has not experienced a pleasure of browsing thousand of lines of the failed authentication attempts. If you do not yet know what to look for in your auth.log, just run:
> zgrep 'Failed password for illegal user' /var/log/auth.log* | wc -l
On the system which I just tried, the result is 125835! since July of 2006. Yeah yeah — 99.999% of those failed logins are due to silly dictionary attacks, which (unfortunately) work in some % of the cases. Are you sure that your password and passwords of all the users on your system are strong enough to survive such an attack?
Also, I guess, there is a (hopefully small) group of system administrators, who experienced a pleasure of DoS attack on their services. Or web-server admins, who have a pleasure to stare at the attempts to access non-existing (most of the time) on the webserver /php/bla-admin.X.Y.bleh.
For both those groups (as well as for other problems too), there is a straightforward solution — just reject (or in other terms - ban) abuser’s IP as soon as you detect an attempt to get an unauthorized access to your box. Unfortunately, we do not stare at the log files 24×7, so we can not react in time. To substitute such a weak part of the chain in this process, i.e. a human operator, Fail2ban tool was created by Cyril Jaquier.
The idea behind Fail2ban is very simple: temporarily or permanently ban an IP which performed multiple undesired actions, such as unsuccessful authentication, access to restricted area, etc.
Originally it was developed to catch illegal SSH login attempts, but later on it grew up into an easily customizable toolkit for speedy reaction on some events (such as detected failed login attempts) recorded in the log files.
In the following sections I will describe a bit more of internals of Fail2ban configuration, but that knowledge is not really required to get the tool working for you. For that, it is sufficient to run “apt-get install fail2ban”. You might like to read the section on jails below if you simply want to enable some additional jails shipped with the Fail2ban package.
Debian/Ubuntu Presence of Fail2ban
Fail2ban is present in sarge from backports.org, and it is native to Etch and Sid. Sarge version in backports is from a 0.6 branch of the Fail2ban, and it has different configuration scheme than current 0.7 (soon 0.8) branch. 0.7 uses split configuration files and orthogonally separates notions of a filter (pretty much a python regular expression with associated set of files) and an action to be taken (banning via iptables/hosts.deny, or sending an email).
Fail2ban is also present in Ubuntu releases since Dapper release.
Configuration
Default configuration in both branches (0.6 and 0.7) enables ssh logins monitoring right out of the box, so no changes are necessary to get Fail2ban running.
If necessary, all changes in the configuration of Fail2ban 0.6.x have to be made in the original configuration file, and sections can be also enabled via command line switch (-e iirc) (N.B. this cmdline option is specific to Debian release of Fail2ban and is not present in upstream version). 0.7 branch uses completely different configuration scheme, and it is very convenient: any change or addition which has to be done in file /etc/fail2ban/X.conf can simply be made in file /etc/fail2ban/X.local — parameters in .local override ones in .conf. This way .conf file stays intact, and during your upgrade there is no necessity to mess with patching config files if they get changed upstream. Since I prefer 0.7 branch, I will describe details of its configuration.
As I mentioned above, 0.7 branch comes with an orthogonal configuration between filters and actions. A filter specifies what to
look for (like a ‘failed login attempt from …’ in auth.log, or a message ‘please brew some coffee, Mike’ in your .xchat/history/private.log), and an action describes possible scenario to play (to ban an IP, or to send an a single packet authenticator to a coffee maker to start brewing a fresh cup of coffee).
Filter
So here is an example of a filter:
> grep -v '^#' /etc/fail2ban/filter.d/sshd.conf [Definition] failregex = Authentication failure for .* from <HOST> Failed [-/\w]+ for .* from <HOST> ROOT LOGIN REFUSED .* FROM <HOST> [iI](?:llegal|nvalid) user .* from <HOST> ignoreregex =
“failregex” is a list of python regular expressions (with “” simply be a shortcut for “(?:::f{4,6}:)?(?P<host>\S+)” to match an IP or a host name. “ignoreregex” allows to infiltrate some false positives.
Standard sid Debian installation of Fail2ban comes with filters for various services (ssh, ftp, http), various implementations (exim, postfix; proftpd, pure-ftpd, wuftpd, etc), and for some additional events (normal illegal login in ssh vs DDOS attack on sshd).
If you want to write your own filter to store under /etc/fail2ban/filter.d/blah.conf, there is a very handy helper tool: fail2ban-regex, which can test your regular expression on the existing logfile and tell if you it works fine.
> fail2ban-regex /var/log/auth.log 'Failed [-/\w]+ for .* from <HOST>’ Running tests ============= Use regex line : Failed [-/\w]+ for .* from <HOST> Use log file : /var/log/auth.log Results ======= Failregex: [1] Failed [-/\w]+ for .* from <HOST> Number of matches: [1] 2 match(es) Addresses found: [1] 69.115.175.240 (Sun Apr 01 23:58:20 2007) 69.115.175.240 (Sun Apr 01 23:58:27 2007) Date template hits: 2 hit: Month Day Hour:Minute:Second 0 hit: Weekday Month Day Hour:Minute:Second Year 0 hit: Year/Month/Day Hour:Minute:Second 0 hit: Day/Month/Year:Hour:Minute:Second 0 hit: Year-Month-Day Hour:Minute:Second 0 hit: TAI64N 0 hit: Epoch Success, the total number of match is 2 However, look at the above section ‘Running tests’ which could contain important information.
Here instead of regular expression to test, you could simply provide the file of you tentative filter.
Action
A typical action for most of the cases would be to ban detected IP of an abuser using iptables, and that action is described in the following Fail2ban action definition:
> sudo grep -v '^#' /etc/fail2ban/action.d/iptables.conf [Definition] actionstart = iptables -N fail2ban-<name> iptables -A fail2ban-<name> -j RETURN iptables -I INPUT -p <protocol> –dport <port> -j fail2ban-<name> actionstop = iptables -D INPUT -p <protocol> –dport <port> -j fail2ban-<name> iptables -F fail2ban-<name> iptables -X fail2ban-<name> actioncheck = iptables -n -L INPUT | grep -q fail2ban-<name> actionban = iptables -I fail2ban-<name> 1 -s <ip> -j DROP actionunban = iptables -D fail2ban-<name> -s <ip> -j DROP [Init] name = default port = ssh protocol = tcp
Default action in 0.7 branch of Debian package though is iptables-multiport, which can be used to ban multiple ports at once. Besides it, there are other actions available such as
- hostsdeny — ban using hosts.deny mechanism
- shorewall,ipfw — use firewall cmdline interfact to ban/allow an IP
- mail-* — email about the performed action to a sysadmin
Jail
And now we came to a point where both notions (filter + action) should be used together. “Jail” is the specification containing a filter and desired set of actions to be performed. Here is an example from original upstream version of /etc/fail2ban/jail.conf.
[ssh-iptables] enabled = false filter = sshd action = iptables[name=SSH, port=ssh, protocol=tcp] mail-whois[name=SSH, dest=yourmail@mail.com] logpath = /var/log/sshd.log maxretry = 5
In this example, the jail ssh-iptables defines the name of the filter to be used (so the full file name is implied to be /etc/fail2ban/filters.d/sshd.conf). Also it defines the list of actions to be performed: TCP port 22 has to be banned after 5 unsuccessful attempts, and an email has to be sent to yourmail@mail.com informing about such action.
While preparing Debian package of Fail2ban, I tuned up Debian-shipped version of jail.conf so that jail specifications becomes minimalistic, since most often all the jails should perform the same chosen action. If there is a need in a jail-specific action, it can always be specified in “action” parameter of the jail. The same jail in Debian-shipped jail.conf looks like
[ssh] enabled = true port = ssh,sftp filter = sshd logpath = /var/log/auth.log maxretry = 6
Since the rest of the jails present in jail.conf are not active by default, desired jails can easily be enabled in /etc/fail2ban/jail.local. Here you can see a part of my locally customized jail.local:
[DEFAULT] bantime = 3600 destemail = root@localhost banaction = shorewall action = %(action_mwl)s [apache] enabled = true maxretry = 4 [sasl] enabled = true [courierauth] enabled = true # custom jail which used to be not present in shipped jail.conf [apache-noscript] enabled = true port = http filter = apache-noscript logpath = /var/log/apache*/*error.log maxretry = 6
Screenshots
Weblinks
Posted in Debian, Ubuntu | 16 Comments »