Table of Contents

Diese Seite ist von der Webseite großteils kopiert http://crycode.de/wiki/Fail2Ban

Fail2Ban

Häufig kommt es vor, dass einzelne Benutzer oder automatisierte Scripts an einem Server verschiedene Kombinationen aus Benutzernamen und Passwörtern “ausprobieren” (das sogenannte Burte-Force) mit dem Ziel einen funktionierenden Login zu finden. Dies wollen wir natürlich verhindern und die Verursacher wirkungsvoll aussperren, wobei uns das Tool Fail2Ban behilflich ist.

Fail2Ban ist ein kleines Programm auf Python-Basis, welches die Logdateien der Server durchsucht und IP-Adressen die zu viele fehlgeschlagene Loginversuche haben blockiert. Das Blockieren der IP-Adressen geschieht dabei in der Regel über Firewallregeln, welche von Fail2Ban entsprechend angepasst werden.

In dieser Anleitung werden wir die, bei Linux üblichen, Iptables verwenden. Weiterhin bringt Fail2Ban aber auch Unterstützung für z.B. Shorewall mit und lässt sich beliebig an die auf dem System eingesetzte Firewall anpassen.

Von Hause aus unterstützt die aktuelle Version von Fail2Ban nur IPv4-Adressen. Durch eine recht kleine Anpassung lässt es sich jedoch auch auf IPv6 erweitern.

Installation

Unter Debian und Ubuntu Linux ist die Installation von Fail2Ban gewohnt einfach und ggf. fehlende Abhängigkeiten werden automatisch mit installiert:

root@meinserver:~# apt-get install fail2ban

Damit ist die Installation auch schon vollständig und Fail2Ban wurde bereits gestartet.

root@meinserver:~# /etc/init.d/fail2ban status
Status of authentication failure monitor:fail2ban is running.

Konfiguration

Die gesamten Einstellungen von Fail2Ban befindet sich im Verzeichnis /etc/fail2ban/.

Die grundlegende Konfiguration erfolgt in der Datei jail.local, welche eine Kopie der jail.conf darstellt. Anpassungen könnten auch in der jail.conf vorgenommen werden, jedoch wird diese bei einem Update eventuell überschrieben. Sobald die Datei jail.local vorhanden ist wird diese von Fail2Ban verwendet und unsere Konfiguration bleibt auch bei einem Update erhalten. Zuerst müssen wir also die jail.conf als jail.local kopieren und anschließend passen wir die jail.local nach unsern Vorstellungen an.

root@meinserver:~# cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
root@meinserver:~# nano /etc/fail2ban/jail.local

Die Konfigurationsdateien sind in verschiedene Sektionen unterteilt. Eine Sektion wird durch eckige Klammern gekennzeichnet (z.B. [ssh]).

Die DEFAULT-Sektion stellt dabei eine Besonderheit dar. Die hier vorgenommenen Einstellungen gelten für alle anderen Sektionen, sofern ein Wert nicht in einer Sektion erneut gesetzt wird. Ansonsten sind die Einstellungen nur für die jeweils aktuelle Sektion gültig.

Die DEFAULT-Sektion

Bei ignoreip können IP-Adressen angegeben werden die nie geblockt werden sollen. Es empfiehlt sich hier zumindest während der Konfiguration seine eigene IP hinzuzufügen.

Unter bantime wird die Bannzeit in Sekunden angegeben. Wir belassen es hier bei dem voreingestellten Wert von 600 (entspricht 10 Minuten).

maxretry gibt die Anzahl der Fehlversuche an, ab der er eine Aktion ausgelöst wird.

Bei destemail kann eine E-Mail Adresse angegeben werden, an die Benachrichtigungen gesendet werden, wenn Fail2Ban eine IP-Adresse blockiert.

banaction legt fest, welche Aktion zum Blockieren einer IP angewendet werden soll. Wir belassen diese bei iptables-multiport, da damit gleich mehrere Ports gesperrt werden können.

Den Eintag bei action ändern wir auf %(action_mwl)s damit wir beim Blockieren einer IP-Adresse eine E-Mail mit ein paar Informationen zugesendet bekommen.

Andere Sektionen, die sogenannten Jails

In jeder Sektion kann eine Einstellung aus der DEFAULT-Sektion (z.B. bantime) überschieben werden.

Nicht benötigte Jails sollten deaktiviert werden.

Erforderlich sind in den Sektionen die folgenden Einstellungen:
* enabled legt fest, ob die Sektion aktiviert ist oder nicht.
* port gibt den Port oder die Ports an die für die IP gesperrt werden sollen
* filter definiert den verwendeten Filter für diese Sektion. Alle verfügbaren Filter befinden sich im Verzeichnis /etc/fail2ban/filter.d/.
* logpath legt die Logdatei fest, welche überwacht werden soll.

Beispiel einer jail.local

jail.local
# Fail2Ban configuration file.
#
# This file was composed for Debian systems from the original one
#  provided now under /usr/share/doc/fail2ban/examples/jail.conf
#  for additional examples.
#
# To avoid merges during upgrades DO NOT MODIFY THIS FILE
# and rather provide your changes in /etc/fail2ban/jail.local
#
# Author: Yaroslav O. Halchenko
#
# $Revision: 281 $
#
 
# The DEFAULT allows a global definition of the options. They can be override
# in each jail afterwards.
 
[DEFAULT]
 
# "ignoreip" can be an IP address, a CIDR mask or a DNS host
ignoreip = 127.0.0.1
bantime  = 900
findtime = 900
maxretry = 5
 
# "backend" specifies the backend used to get files modification. Available
# options are "gamin", "polling" and "auto".
# yoh: For some reason Debian shipped python-gamin didn't work as expected
#      This issue left ToDo, so polling is default backend for now
backend = polling
 
#
# Destination email address used solely for the interpolations in
# jail.{conf,local} configuration files.
destemail = root@localhost
 
#
# ACTIONS
#
 
# Default banning action (e.g. iptables, iptables-new,
# iptables-multiport, shorewall, etc) It is used to define 
# action_* variables. Can be overriden globally or per 
# section within jail.local file
banaction = iptables-multiport
 
# email action. Since 0.8.1 upstream fail2ban uses sendmail
# MTA for the mailing. Change mta configuration parameter to mail
# if you want to revert to conventional 'mail'.
mta = sendmail
 
# Default protocol
protocol = tcp
 
#
# Action shortcuts. To be used to define action parameter
 
# The simplest action to take: ban only
action_ = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s]
 
# ban & send an e-mail with whois report to the destemail.
action_mw = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s]
              %(mta)s-whois[name=%(__name__)s, dest="%(destemail)s", protocol="%(protocol)s]
 
# ban & send an e-mail with whois report and relevant log lines
# to the destemail.
action_mwl = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s]
               %(mta)s-whois-lines[name=%(__name__)s, dest="%(destemail)s", logpath=%(logpath)s]
 
# Choose default action.  To change, just override value of 'action' with the
# interpolation to the chosen action shortcut (e.g.  action_mw, action_mwl, etc) in jail.local
# globally (section [DEFAULT]) or per specific section 
action = %(action_mwl)s
 
#
# JAILS
#
 
# Next jails corresponds to the standard configuration in Fail2ban 0.6 which
# was shipped in Debian. Enable any defined here jail by including
#
# [SECTION_NAME] 
# enabled = true
 
#
# in /etc/fail2ban/jail.local.
#
# Optionally you may override any other parameter (e.g. banaction,
# action, port, logpath, etc) in that section within jail.local
 
[ssh]
 
enabled = true
#port  = ssh
filter  = sshd
banaction = iptables-allports
protocol = all
port = anyport
logpath  = /var/log/auth.log
# findtime: 1 week
findtime = 604800
# bantime: 1 week
bantime = 604800
maxretry = 5
 
 
# Generic filter for pam. Has to be used with action which bans all ports
# such as iptables-allports, shorewall
[pam-generic]
 
enabled = false
# pam-generic filter can be customized to monitor specific subset of 'tty's
filter  = pam-generic
# port actually must be irrelevant but lets leave it all for some possible uses
port = all
banaction = iptables-allports
port     = anyport
logpath  = /var/log/auth.log
maxretry = 6
 
[xinetd-fail]
 
enabled   = false
filter    = xinetd-fail
port      = all
banaction = iptables-multiport-log
logpath   = /var/log/daemon.log
maxretry  = 2
 
 
[ssh-ddos]
 
enabled = true
port    = ssh
filter  = sshd-ddos
logpath  = /var/log/auth.log
maxretry = 6
 
#
# HTTP servers
#
 
[apache]
 
enabled = true
port  = http,https
filter  = apache-auth
logpath = /var/log/apache*/*error.log
maxretry = 6
 
# default action is now multiport, so apache-multiport jail was left
# for compatibility with previous (<0.7.6-2) releases
[apache-multiport]
 
enabled   = false
port    = http,https
filter    = apache-auth
logpath   = /var/log/apache*/*error.log
maxretry  = 6
 
[apache-noscript]
 
enabled = false
port    = http,https
filter  = apache-noscript
logpath = /var/log/apache*/*error.log
maxretry = 6
 
[apache-overflows]
 
enabled = false
port    = http,https
filter  = apache-overflows
logpath = /var/log/apache*/*error.log
maxretry = 2
 
#
# FTP servers
#
 
[vsftpd]
 
enabled  = false
port   = ftp,ftp-data,ftps,ftps-data
filter   = vsftpd
logpath  = /var/log/vsftpd.log
# or overwrite it in jails.local to be
# logpath = /var/log/auth.log
# if you want to rely on PAM failed login attempts
# vsftpd's failregex should match both of those formats
maxretry = 6
 
 
[proftpd]
 
enabled  = false
port   = ftp,ftp-data,ftps,ftps-data
filter   = proftpd
logpath  = /var/log/proftpd/proftpd.log
maxretry = 6
 
 
[wuftpd]
 
enabled  = false
port   = ftp,ftp-data,ftps,ftps-data
filter   = wuftpd
logpath  = /var/log/auth.log
maxretry = 6
 
 
#
# Mail servers
#
 
[postfix]
 
enabled  = false
port   = smtp,ssmtp
filter   = postfix
logpath  = /var/log/mail.log
 
 
[couriersmtp]
 
enabled  = false
port   = smtp,ssmtp
filter   = couriersmtp
logpath  = /var/log/mail.log
 
 
#
# Mail servers authenticators: might be used for smtp,ftp,imap servers, so
# all relevant ports get banned
#
 
[courierauth]
 
enabled  = false
port   = smtp,ssmtp,imap2,imap3,imaps,pop3,pop3s
filter   = courierlogin
logpath  = /var/log/mail.log
 
 
[sasl]
 
enabled  = false
port   = smtp,ssmtp,imap2,imap3,imaps,pop3,pop3s
filter   = sasl
# You might consider monitoring /var/log/warn.log instead
# if you are running postfix. See http://bugs.debian.org/507990
logpath  = /var/log/mail.log
 

Webmin überwachen lassen

Weiterhin können wir durch den folgenden Eintrag in der jail.local das Verwaltungstool Webmin überwachen lassen.

# Webmin
[webmin-auth]
enabled = true
port    = 65432
filter  = webmin-auth
logpath  = /var/log/auth.log
maxretry = 5

Mehrfach geblockte Hosts längere Zeit aussperren

Sinnvoll ist es außerdem Hosts längere Zeit auszusperren nachdem sie mehrfach durch ein anderes Jail geblock wurden.

Hierfür tragen wir am Ende der jail.local folgendes ein:

# Fail2Ban
[fail2ban]
enabled = true
filter = fail2ban
banaction = iptables-allports
protocol = all
port = anyport
logpath = /var/log/fail2ban.log
# findtime: 1 week
findtime = 604800
# bantime: 1 week
bantime = 604800
maxretry = 5

Zusätzlich müssen wir noch die passenden Filterregeln in der Datei /etc/fail2ban/filter.d/fail2ban.conf erstellen:

[Definition]
failregex = fail2ban.actions: WARNING \[(.*)\] Ban <HOST>
ignoreregex = fail2ban.actions: WARNING \[fail2ban\] Ban <HOST>

Neustart von Fail2Ban

Zum Schluss starten wir Fail2Ban neu um alle Anpassungen zu aktivieren.

root@meinserver:~# /etc/init.d/fail2ban restart
Restarting authentication failure monitor: fail2ban.

Nun ist Fail2Ban aktiv und überwacht pausenlos die in der jail.local eingestellten Logdateien.

IPv6

Von Hause aus unterstützt die aktuelle Version von Fail2Ban nur IPv4-Adressen. Durch eine recht kleine Anpassung lässt es sich jedoch auch auf IPv6 erweitern. Im folgenden Abschnitt wird beschrieben welche Anpassungen vorgenommen werden müssen, damit Fail2Ban auch IPv6 Adressen erkennt und ggf. blockiert.

IPv4/IPv6 Weiche

Zuerst muss die Datei /usr/bin/ip64tables als Weiche zwischen IPv4 und IPv6 mit folgendem Inhalt erstellt werden:

ip64tables
#!/bin/bash
# iptables-Weiche
LINE=$*
 
RESULT=`echo $LINE | egrep " ([0-9]{1,3}\.){3}[0-9]{1,3}" | wc -l`
RESULT6=`echo $LINE | egrep "(::[A-Fa-f0-9])|((:[A-Fa-f0-9]{1,4}){2,})" | wc -l `
 
if [ $RESULT -eq "1" ]; then
	# IPv4
	iptables $LINE
	ERRCODE=$?
 
elif [ $RESULT6 -eq "1" ]; then
	# IPv6
	ip6tables $LINE
	ERRCODE=$?
 
else
	# IPv4 und IPv6
	iptables $LINE
	ERRCODE=$?
	ip6tables $LINE
	if [ $? -ge "1" ]; then
		ERRCODE=$?
	fi
 
fi
 
exit $ERRCODE

Anschließend machen wir die Datei noch ausführbar:

root@meinserver~# chmod +x /usr/bin/ip64tables

Neue Aktionen bei Fail2Ban hinzufügen

Im Verzeichnis /etc/fail2ban/action.d/ legen wir die drei Dateien mit folgendem Inhalt an:

ip64tables-multiport.conf
[INCLUDES]
before = iptables-blocktype.conf
 
[Definition]
actionstart = ip64tables -N fail2ban-<name>
              ip64tables -A fail2ban-<name> -j RETURN
              ip64tables -I INPUT -p <protocol> -m multiport --dports <port> -j fail2ban-<name>
actionstop = ip64tables -D INPUT -p <protocol> -m multiport --dports <port> -j fail2ban-<name>
             ip64tables -F fail2ban-<name>
             ip64tables -X fail2ban-<name>
actioncheck = ip64tables -n -L INPUT | grep -q fail2ban-<name>
actionban = ip64tables -I fail2ban-<name> 1 -s <ip> -j <blocktype>
actionunban = ip64tables -D fail2ban-<name> -s <ip> -j <blocktype>
 
[Init]
name = default
port = ssh
protocol = tcp
ip64tables-allports.conf
[INCLUDES]
before = iptables-blocktype.conf
 
[Definition]
actionstart = ip64tables -N fail2ban-<name>
              ip64tables -A fail2ban-<name> -j RETURN
              ip64tables -I INPUT -p <protocol> -j fail2ban-<name>
actionstop = ip64tables -D INPUT -p <protocol> -j fail2ban-<name>
             ip64tables -F fail2ban-<name>
             ip64tables -X fail2ban-<name>
actioncheck = ip64tables -n -L INPUT | grep -q fail2ban-<name>
actionban = ip64tables -I fail2ban-<name> 1 -s <ip> -j <blocktype>
actionunban = ip64tables -D fail2ban-<name> -s <ip> -j <blocktype>
 
[Init]
name = default
protocol = tcp
iptables-blocktype.local
# Fail2Ban configuration file
#
# Author: Daniel Black
#
# This is a included configuration file and includes the defination for the blocktype
# used in all iptables based actions by default.
#
# The user can override the default in iptables-blocktype.local
 
[Init]
 
# Option:  blocktype
# Note:    This is what the action does with rules. This can be any jump target
#          as per the iptables man page (section 8). Common values are DROP
#          REJECT, REJECT --reject-with icmp-port-unreachable
# Values:  STRING
#
#--reject-with icmp-port-unreachable ist nicht moeglich, da ipv6 nicht damit funktioniert. diese option ist aber der standart von REJECT
blocktype = REJECT

Fail2Ban-Dateien Patchen

Damit Fail2Ban die IPv6-Adressen auch richtig erkennt müssen die beiden Dateien failregex.py und filter.py gepachtet werden. Je nach Fail2Ban-Version sind dafür unterschiedliche Patches nötig.

Die aktuell verwendete Version von Fail2Ban kann über den folgenden Befehl ermittelt werden:

benutzer@meinserver:~$ fail2ban-server -V
Fail2Ban v0.8.13
 
Copyright (c) 2004-2008 Cyril Jaquier, 2008- Fail2Ban Contributors
Copyright of modifications held by their respective authors.
Licensed under the GNU General Public License v2 (GPL).
 
Written by Cyril Jaquier <cyril.jaquier@fail2ban.org>.
Many contributions by Yaroslav O. Halchenko <debian@onerussian.com>.

Abhängig von der Version legen wir zuerst die zwei patch-Dateien im Verzeichnis /tmp an:

für Fail2Ban v0.8.13 (Debian jessie, Ubuntu trusty/utopic)

failregex.patch
# Fail2Ban IPv6 Patch for Fail2Ban v0.8.13
--- failregex.py.orig
+++ failregex.py
@@ -41,7 +41,7 @@
 		self._matchCache = None
 		# Perform shortcuts expansions.
 		# Replace "<HOST>" with default regular expression for host.
-		regex = regex.replace("<HOST>", "(?:::f{4,6}:)?(?P<host>[\w\-.^_]+)")
+		regex = regex.replace("<HOST>", "(?:::f{4,6}:)?(?P<host>[\w\-.^_:]+)")
 		if regex.lstrip() == '':
 			raise RegexException("Cannot add empty regex")
 		try:
filter.patch
# Fail2Ban IPv6 Patch for Fail2Ban v0.8.13
--- filter.py.orig
+++ filter.py
@@ -655,6 +655,7 @@
 class DNSUtils:
 
 	IP_CRE = re.compile("^(?:\d{1,3}\.){3}\d{1,3}$")
+	IP_CRE6 = re.compile("^(?:[0-9:A-Fa-f]{3,})$")
 
 	#@staticmethod
 	def dnsToIp(dns):
@@ -678,19 +679,21 @@
 		if match:
 			return match
 		else:
-			return None
+			match = DNSUtils.IP_CRE6.match(text)
+			if match:
+				""" Right Here, we faced to a ipv6
+				"""
+				return match
+			else:
+				return None
 	searchIP = staticmethod(searchIP)
 
 	#@staticmethod
 	def isValidIP(string):
 		""" Return true if str is a valid IP
+		We Consider that logfiles didn't make errors ;) 
 		"""
-		s = string.split('/', 1)
-		try:
-			socket.inet_aton(s[0])
-			return True
-		except socket.error:
-			return False
+		return True
 	isValidIP = staticmethod(isValidIP)
 
 	#@staticmethod

Anschließend wenden wir die beiden Patches noch an:

root@meinserver:~# patch -l -b /usr/share/fail2ban/server/failregex.py /tmp/failregex.patch
patching file /usr/share/fail2ban/server/failregex.py
 
root@meinserver:~# patch -l -b /usr/share/fail2ban/server/filter.py /tmp/filter.patch
patching file /usr/share/fail2ban/server/filter.py

Durch den Parameter -b wird beim Patchen jeweils ein Backup der Originaldatei (failregex.py.orig bzw. filter.py.orig angelegt. Sollte etwas schief gehen kann damit jederzeit der Ausgangszustand wiederhergestellt werden.

Abschließend müssen die beiden Dateien noch neu compiled werden:

root@meinserver:~# pycompile /usr/share/fail2ban/server/failregex.py
 
root@meinserver:~# pycompile /usr/share/fail2ban/server/filter.py

Einstellungen in der Datei jail.local anpassen

Damit Fail2Ban die neuen Aktionen verwendet müssen alle banaction-Einträge in der jail.local angepasst werden.

Dabei ändern wir überall in der Datei iptables-multiport in ip64tables-multiport und iptables-allports in ip64tables-allports. Sollten noch andere Aktionen im Einsatz sein, so müssen diese ggf. auch angepasst werden.

Fail2Ban neustarten und iptables sowie ip6tables kontrollieren

root@meinserver:~# service fail2ban restart

Nun kontrollieren wir noch die aktuellen iptables und ip6tables.

root@meinserver:~# iptables -L -n -v
root@meinserver:~# ip6tables -L -n -v

Wenn alles geklappt hat sind jetzt in den Ausgaben die Regeln und Ketten (Chain) von Fail2Ban zu sehen.