{"id":2546,"date":"2017-02-02T02:00:30","date_gmt":"2017-02-02T01:00:30","guid":{"rendered":"http:\/\/speefak.spdns.de\/oss_lifestyle\/?p=2546"},"modified":"2024-06-02T17:18:07","modified_gmt":"2024-06-02T15:18:07","slug":"server-mit-fail2ban-sichern","status":"publish","type":"post","link":"https:\/\/speefak.spdns.de\/oss_lifestyle\/server-mit-fail2ban-sichern\/","title":{"rendered":"Server mit Fail2ban sichern"},"content":{"rendered":"<p><a href=\"http:\/\/www.fail2ban.org\/wiki\/index.php\/FAQ_german\" target=\"_blank\" rel=\"noopener noreferrer\">Fail2Ban<\/a> ist eine auf Python basierte Skriptsammlung f\u00fcr Linux Server und Systeme, die es Administratoren erm\u00f6glicht, die Sicherheit ihres Systems zu erh\u00f6hen und sich vor Angriffen zu sch\u00fctzen, die auf wiederholte Anmeldeversuche abzielen, indem es fehlgeschlagene Anmeldeversuche \u00fcberwacht und tempor\u00e4re Sperrma\u00dfnahmen auf IP-Adressen anwendet, die verd\u00e4chtige oder b\u00f6sartige Aktivit\u00e4ten zeigen. Da zu z\u00e4hlen:<\/p>\n<ul>\n<li>\n<ul>\n<li><strong>Schutz vor Brute-Force-Angriffen<\/strong>: Fail2ban ist besonders n\u00fctzlich, um sich gegen Brute-Force-Angriffe zu verteidigen, bei denen Angreifer wiederholt versuchen, sich mit verschiedenen Benutzernamen und Kennw\u00f6rtern anzumelden, um unbefugten Zugriff zu erlangen.<\/li>\n<li><strong>Konfigurierbare Regeln<\/strong>: Sie k\u00f6nnen Fail2ban so konfigurieren, dass es spezifische Dienste wie SSH, Apache, FTP und mehr \u00fcberwacht. Es erm\u00f6glicht die Definition von Regeln, die auf Log-Dateien basieren, um verd\u00e4chtige Aktivit\u00e4ten zu erkennen.<\/li>\n<li><strong>Zeitlich begrenzte Sperren<\/strong>: Wenn ein Benutzer oder eine IP-Adresse gegen eine Regel verst\u00f6\u00dft, wird er\/sie tempor\u00e4r gesperrt. Die Dauer der Sperre ist konfigurierbar und kann je nach Bedarf angepasst werden.<\/li>\n<li><strong>Zentrale Protokollierung<\/strong>: Fail2ban protokolliert alle Aktivit\u00e4ten, einschlie\u00dflich Sperrungen und Freigaben, um die \u00dcberwachung und Fehlersuche zu erleichtern.<\/li>\n<li><strong>Benutzerdefinierte Aktionen<\/strong>: Sie k\u00f6nnen benutzerdefinierte Aktionen festlegen, die bei einer Sperre ausgef\u00fchrt werden sollen, z.B. Benachrichtigungen per E-Mail oder das Hinzuf\u00fcgen von IP-Adressen zu einer Blockliste.<\/li>\n<li><strong>Erweiterbarkeit<\/strong>: Es gibt viele Erweiterungen und Plugins f\u00fcr Fail2ban, die zus\u00e4tzliche Funktionalit\u00e4ten bieten, um den Schutz zu verbessern.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>Technisch versierte Nutzer k\u00f6nnen eigene Muster in Error- bzw. Access-Logs erkennen und so weitere Firewall-Regeln definieren.<a id=\"overview\"><\/a><\/p>\n<table>\n<tbody>\n<tr>\n<td>Grundlagen<\/td>\n<td>Jails \/ Filter<\/td>\n<td>Sonstiges<\/td>\n<\/tr>\n<tr>\n<td><\/td>\n<td><\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td><a href=\"#Installation\">Installation<\/a><\/td>\n<td><a href=\"#SSH_Jail\">SSH (mit Erkl\u00e4rung \/ BSP)<\/a><\/td>\n<td><a href=\"#Fail2Ban_Email_Support\">Fail2Ban E-Mail Support<\/a><\/td>\n<\/tr>\n<tr>\n<td><a href=\"#Konfiguration\">Konfiguration<\/a><\/td>\n<td><a href=\"#Wordpress_Jail\">WordPress<\/a><\/td>\n<td>\u00a0<a href=\"#Manuelle_IP-Sperre_via_Blacklist\">Manuelle IP-Sperre via Blacklist<\/a><\/td>\n<\/tr>\n<tr>\n<td><a href=\"#Die_einzelnen_Jails\">Die einzelnen Jails<\/a><\/td>\n<td><a href=\"#Nextcloud_Jail\">Nextcloud<\/a><\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td><\/td>\n<td><\/td>\n<td>\u00a0<a href=\"#Fail2ban_steuern\">Fail2ban Steuern<\/a><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2>Installation<a id=\"Installation\"><\/a><\/h2>\n<p>Fail2Ban ist in den Standardrepositories g\u00e4ngiger Distributionen bereits enthalten und kann auf Debian basierten Systemen wie gewohnt einfach installiert werden :<\/p>\n<pre class=\"theme:dark-terminal lang:sh decode:true\">sudo apt-get install fail2ban<\/pre>\n<hr \/>\n<p style=\"text-align: center;\"><strong><em><a href=\"#overview\">Zur\u00fcck zur \u00dcbersicht<\/a><\/em><\/strong><\/p>\n<hr \/>\n<h2>Konfiguration<a id=\"Konfiguration\"><\/a><\/h2>\n<p>Nach erfolgreicher Installation befinden sich die Konfigurationsdateien im Verzeichnis <strong><em>\/etc\/fail2ban<\/em><\/strong>. In der <em><strong>fail2ban.conf<\/strong>\u00a0 <\/em>werden die grundlegenden Parameter f\u00fcr Fail2Ban festgelegt. Die allgemeine Konfiguration der Jails wird in der Datei\u00a0<strong><em> jail.local<\/em><\/strong> realisiert, nicht in der jail.conf, da diese bei Updates \u00fcberschrieben wird.<\/p>\n<pre class=\"theme:dark-terminal lang:sh decode:true \"># To avoid merges during upgrades DO NOT MODIFY THIS FILE\r\n# and rather provide your changes in \/etc\/fail2ban\/jail.local<\/pre>\n<p>Die jail.conf sollte daher zu jail.local kopiert oder einfach auf jail.conf verlinkt werden<\/p>\n<pre class=\"theme:dark-terminal lang:sh decode:true\">cd \/etc\/fail2ban &amp;&amp; sudo mv jail.conf jail.local &amp;&amp; sudo ln -s jail.local jail.conf<\/pre>\n<p>In der [DEFAULT] Sektion am Anfang der jail.local werden die globalen Parameter, wie beispielsweise Loglevel oder E-Mail-Adresse f\u00fcr Statusmeldungen, aller Jails gesetzt. Die Parameter k\u00f6nnen dabei f\u00fcr jeden Jail weiterhin separat konfiguriert werden, sofern diese in der betreffenden Jail Sektion oder Datei \/etc\/fail2ban\/jail.d\/&lt;jailname&gt;.conf angeben werden. Die jail.local ist damit eine Art &#8220;Fallback Konfigurtion&#8221; der Jails. Globale Parameter sind beispielsweise folgende:<\/p>\n<pre class=\"theme:dark-terminal lang:sh decode:true\">ignoreip = 127.0.0.1\r\nbantime  = 3600\r\nmaxretry = 3\r\n<\/pre>\n<hr \/>\n<p style=\"text-align: center;\"><span style=\"text-decoration: underline;\"><strong><em><a href=\"#overview\">Zur\u00fcck zur \u00dcbersicht<\/a><\/em><\/strong><\/span><\/p>\n<hr \/>\n<h2>Die einzelnen Jails<a id=\"Die_einzelnen_Jails\"><\/a><\/h2>\n<p>Die einzelnen Jails k\u00f6nnen in der Datei <em><strong>\/etc\/fail2ban\/jail.d\/defaults-debian.conf<\/strong><\/em> oder einzeln in<strong> \/etc\/fail2ban\/jail.d\/&lt;jailname&gt;.conf<\/strong>\u00a0 aktiviert und konfiguriert werden. Aktionen wie das Sperren der IP, Emailversand oder sonstige Aktionen werden hier definiert. Der Filter, der auf die unter dem Parameter logpath zugewiesenen Logdatei angewandt wird, ist in dem Verzeichnis <em><strong>\/etc\/fail2ban\/filter.d\/*.conf<\/strong><\/em> unter der entsprechen *.conf Datei definiert und wird mit dem Parameter &#8220;filter = &lt;Filter Name&gt; zugewiesen. Nachfolgend sind einige Filter und deren Konfigurationen aufgelistet.<\/p>\n<hr \/>\n<p style=\"text-align: center;\"><span style=\"text-decoration: underline;\"><strong><em><a href=\"#overview\">Zur\u00fcck zur \u00dcbersicht<\/a><\/em><\/strong><\/span><\/p>\n<hr \/>\n<p><span style=\"text-decoration: underline;\">SSH<a id=\"SSH_Jail\"><\/a><\/span><\/p>\n<p>\/etc\/fail2ban\/sshd.conf :<\/p>\n<pre class=\"theme:dark-terminal lang:sh decode:true\">[ssh]\r\nenabled = true\r\nfilter = sshd\r\nport = ssh\r\nlogpath = \/var\/log\/auth.log\r\n# banaction = iptables-multiport  # per default gesetzt\r\nmaxretry = 6\r\nfindtime = 86400\r\nbantime = 3600<\/pre>\n<p>\/etc\/fail2ban\/filter.d\/sshd.conf<\/p>\n<pre class=\"theme:dark-terminal height-set:true height:100 lang:sh decode:true\"># Fail2Ban filter for openssh\r\n#\r\n# If you want to protect OpenSSH from being bruteforced by password\r\n# authentication then get public key authentication working before disabling\r\n# PasswordAuthentication in sshd_config.\r\n#\r\n#\r\n# \"Connection from &lt;HOST&gt; port \\d+\" requires LogLevel VERBOSE in sshd_config\r\n#\r\n\r\n[INCLUDES]\r\n\r\n# Read common prefixes. If any customizations available -- read them from\r\n# common.local\r\nbefore = common.conf\r\n\r\n[DEFAULT]\r\n\r\n_daemon = sshd\r\n\r\n# optional prefix (logged from several ssh versions) like \"error: \", \"error: PAM: \" or \"fatal: \"\r\n__pref = (?:(?:error|fatal): (?:PAM: )?)?\r\n# optional suffix (logged from several ssh versions) like \" [preauth]\"\r\n__suff = (?: \\[preauth\\])?\\s*\r\n__on_port_opt = (?: port \\d+)?(?: on \\S+(?: port \\d+)?)?\r\n\r\n# for all possible (also future) forms of \"no matching (cipher|mac|MAC|compression method|key exchange method|host key type) found\",\r\n# see ssherr.c for all possible SSH_ERR_..._ALG_MATCH errors.\r\n__alg_match = (?:(?:\\w+ (?!found\\b)){0,2}\\w+)\r\n\r\n[Definition]\r\n\r\nprefregex = ^&lt;F-MLFID&gt;%(__prefix_line)s&lt;\/F-MLFID&gt;%(__pref)s&lt;F-CONTENT&gt;.+&lt;\/F-CONTENT&gt;$\r\n\r\ncmnfailre = ^[aA]uthentication (?:failure|error|failed) for &lt;F-USER&gt;.*&lt;\/F-USER&gt; from &lt;HOST&gt;( via \\S+)?\\s*%(__suff)s$\r\n            ^User not known to the underlying authentication module for &lt;F-USER&gt;.*&lt;\/F-USER&gt; from &lt;HOST&gt;\\s*%(__suff)s$\r\n            ^Failed \\S+ for invalid user &lt;F-USER&gt;(?P&lt;cond_user&gt;\\S+)|(?:(?! from ).)*?&lt;\/F-USER&gt; from &lt;HOST&gt;%(__on_port_opt)s(?: ssh\\d*)?(?(cond_user): |(?:(?:(?! from ).)*)$)\r\n            ^Failed \\b(?!publickey)\\S+ for (?P&lt;cond_inv&gt;invalid user )?&lt;F-USER&gt;(?P&lt;cond_user&gt;\\S+)|(?(cond_inv)(?:(?! from ).)*?|[^:]+)&lt;\/F-USER&gt; from &lt;HOST&gt;%(__on_port_opt)s(?: ssh\\d*)?(?(cond_user): |(?:(?:(?! from ).)*)$)\r\n            ^&lt;F-USER&gt;ROOT&lt;\/F-USER&gt; LOGIN REFUSED.* FROM &lt;HOST&gt;\\s*%(__suff)s$\r\n            ^[iI](?:llegal|nvalid) user &lt;F-USER&gt;.*?&lt;\/F-USER&gt; from &lt;HOST&gt;%(__on_port_opt)s\\s*$\r\n            ^User &lt;F-USER&gt;.+&lt;\/F-USER&gt; from &lt;HOST&gt; not allowed because not listed in AllowUsers\\s*%(__suff)s$\r\n            ^User &lt;F-USER&gt;.+&lt;\/F-USER&gt; from &lt;HOST&gt; not allowed because listed in DenyUsers\\s*%(__suff)s$\r\n            ^User &lt;F-USER&gt;.+&lt;\/F-USER&gt; from &lt;HOST&gt; not allowed because not in any group\\s*%(__suff)s$\r\n            ^refused connect from \\S+ \\(&lt;HOST&gt;\\)\\s*%(__suff)s$\r\n            ^Received &lt;F-MLFFORGET&gt;disconnect&lt;\/F-MLFFORGET&gt; from &lt;HOST&gt;%(__on_port_opt)s:\\s*3: .*: Auth fail%(__suff)s$\r\n            ^User &lt;F-USER&gt;.+&lt;\/F-USER&gt; from &lt;HOST&gt; not allowed because a group is listed in DenyGroups\\s*%(__suff)s$\r\n            ^User &lt;F-USER&gt;.+&lt;\/F-USER&gt; from &lt;HOST&gt; not allowed because none of user's groups are listed in AllowGroups\\s*%(__suff)s$\r\n            ^pam_unix\\(sshd:auth\\):\\s+authentication failure;\\s*logname=\\S*\\s*uid=\\d*\\s*euid=\\d*\\s*tty=\\S*\\s*ruser=&lt;F-USER&gt;\\S*&lt;\/F-USER&gt;\\s*rhost=&lt;HOST&gt;\\s.*%(__suff)s$\r\n            ^(error: )?maximum authentication attempts exceeded for &lt;F-USER&gt;.*&lt;\/F-USER&gt; from &lt;HOST&gt;%(__on_port_opt)s(?: ssh\\d*)?%(__suff)s$\r\n            ^User &lt;F-USER&gt;.+&lt;\/F-USER&gt; not allowed because account is locked%(__suff)s\r\n            ^&lt;F-MLFFORGET&gt;Disconnecting&lt;\/F-MLFFORGET&gt;: Too many authentication failures(?: for &lt;F-USER&gt;.+?&lt;\/F-USER&gt;)?%(__suff)s\r\n            ^&lt;F-NOFAIL&gt;Received &lt;F-MLFFORGET&gt;disconnect&lt;\/F-MLFFORGET&gt;&lt;\/F-NOFAIL&gt; from &lt;HOST&gt;: 11:\r\n            ^&lt;F-NOFAIL&gt;Connection &lt;F-MLFFORGET&gt;closed&lt;\/F-MLFFORGET&gt;&lt;\/F-NOFAIL&gt; by &lt;HOST&gt;%(__suff)s$\r\n            ^&lt;F-MLFFORGET&gt;&lt;F-NOFAIL&gt;Accepted publickey&lt;\/F-NOFAIL&gt;&lt;\/F-MLFFORGET&gt; for \\S+ from &lt;HOST&gt;(?:\\s|$)\r\n\r\nmdre-normal =\r\n\r\nmdre-ddos = ^Did not receive identification string from &lt;HOST&gt;%(__suff)s$\r\n            ^Connection &lt;F-MLFFORGET&gt;reset&lt;\/F-MLFFORGET&gt; by &lt;HOST&gt;%(__on_port_opt)s%(__suff)s\r\n            ^&lt;F-NOFAIL&gt;SSH: Server;Ltype:&lt;\/F-NOFAIL&gt; (?:Authname|Version|Kex);Remote: &lt;HOST&gt;-\\d+;[A-Z]\\w+:\r\n            ^Read from socket failed: Connection &lt;F-MLFFORGET&gt;reset&lt;\/F-MLFFORGET&gt; by peer%(__suff)s\r\n\r\nmdre-extra = ^Received &lt;F-MLFFORGET&gt;disconnect&lt;\/F-MLFFORGET&gt; from &lt;HOST&gt;%(__on_port_opt)s:\\s*14: No supported authentication methods available%(__suff)s$\r\n            ^Unable to negotiate with &lt;HOST&gt;%(__on_port_opt)s: no matching &lt;__alg_match&gt; found.\r\n            ^Unable to negotiate a &lt;__alg_match&gt;%(__suff)s$\r\n            ^no matching &lt;__alg_match&gt; found:\r\n\r\nmdre-aggressive = %(mdre-ddos)s\r\n                  %(mdre-extra)s\r\n\r\ncfooterre = ^&lt;F-NOFAIL&gt;Connection from&lt;\/F-NOFAIL&gt; &lt;HOST&gt;\r\n\r\nfailregex = %(cmnfailre)s\r\n            &lt;mdre-&lt;mode&gt;&gt;\r\n            %(cfooterre)s\r\n\r\n# Parameter \"mode\": normal (default), ddos, extra or aggressive (combines all)\r\n# Usage example (for jail.local):\r\n#   [sshd]\r\n#   mode = extra\r\n#   # or another jail (rewrite filter parameters of jail):\r\n#   [sshd-aggressive]\r\n#   filter = sshd[mode=aggressive]\r\n#\r\nmode = normal\r\n\r\n#filter = sshd[mode=aggressive]\r\n\r\nignoreregex = \r\n\r\nmaxlines = 1\r\n\r\njournalmatch = _SYSTEMD_UNIT=sshd.service + _COMM=sshd\r\n\r\ndatepattern = {^LN-BEG}\r\n\r\n# DEV Notes:\r\n#\r\n#   \"Failed \\S+ for .*? from &lt;HOST&gt;...\" failregex uses non-greedy catch-all because\r\n#   it is coming before use of &lt;HOST&gt; which is not hard-anchored at the end as well,\r\n#   and later catch-all's could contain user-provided input, which need to be greedily\r\n#   matched away first.\r\n#\r\n# Author: Cyril Jaquier, Yaroslav Halchenko, Petr Voralek, Daniel Black and Sergey Brester aka sebres\r\n# Rewritten using prefregex (and introduced \"mode\" parameter) by Serg G. Brester.\r\n<\/pre>\n<hr \/>\n<p style=\"text-align: center;\"><span style=\"text-decoration: underline;\"><strong><em><a href=\"#overview\">Zur\u00fcck zur \u00dcbersicht<\/a><\/em><\/strong><\/span><\/p>\n<hr \/>\n<p><span style=\"text-decoration: underline;\">WordPress<a id=\"Wordpress_Jail\"><\/a><\/span><\/p>\n<p>\/etc\/fail2ban\/jail.d\/wordpress.conf<\/p>\n<pre class=\"theme:dark-terminal lang:sh decode:true\">[wordpress]\r\nenabled = true\r\nport = http,https\r\nfilter = wordpress\r\nlogpath = \/var\/log\/apache2\/access.log\r\nmaxretry = 6 \r\nfindtime = 86400 \r\nbantime = 3600\r\n<\/pre>\n<p>\/etc\/fail2ban\/filter.d\/wordpress.conf<\/p>\n<pre class=\"theme:dark-terminal lang:sh decode:true\"># Filter for WordPress login\r\n[INCLUDES]\r\nbefore = common.conf\r\n[Definition]\r\nfailregex = &lt;HOST&gt;.*POST.*(wp-login\\.php|xmlrpc\\.php).* 200\r\ndatepattern = %%d\/%%b\/%%Y:%%H:%%M:%%S %%z\r\n<\/pre>\n<hr \/>\n<p style=\"text-align: center;\"><span style=\"text-decoration: underline;\"><strong><em><a href=\"#overview\">Zur\u00fcck zur \u00dcbersicht<\/a><\/em><\/strong><\/span><\/p>\n<hr \/>\n<p><span style=\"text-decoration: underline;\">Nextcloud<a id=\"Nextcloud_Jail\"><\/a><\/span><\/p>\n<p>\/etc\/fail2ban\/jail.d\/nextcloud.conf<\/p>\n<pre class=\"theme:dark-terminal lang:sh decode:true\">[nextcloud]\r\nenabled = true\r\nport = https,http\r\nfilter = nextcloud\r\nlogpath = \/var\/www\/nextcloud\/data\/nextcloud.log\r\nmaxretry = 6\r\nfindtime = 86400\r\nbantime = 1800<\/pre>\n<p>\/etc\/fail2ban\/filter.d\/nextcloud.conf :<\/p>\n<pre class=\"theme:dark-terminal lang:sh decode:true\">[Definition]\r\nfailregex={\"reqId\":\".*\",\"remoteAddr\":\".*\",\"app\":\"core\",\"message\":\"Login failed: '.*' \\(Remote IP: '&lt;HOST&gt;'\\)\",\"level\":2,\"time\":\".*\"}\r\nignoreregex =<\/pre>\n<hr \/>\n<p>Fail2Ban setzt allerdings nicht irgendwelche IP-Adressen auf die interne Blacklist, sondern ausschlie\u00dflich die, die dem regul\u00e4ren Ausdruck aus dem Jail-Filter entsprechen. Daher sollte man sehr vorsichtig mit Filter-Definitionen hantieren und diese mit <a href=\"http:\/\/www.fail2ban.org\/wiki\/index.php\/MANUAL_0_8\" target=\"_blank\" rel=\"noopener noreferrer\">fail2ban-regex<\/a> umgehend testen. Die Funktion der Filter kann mit dem folgenden Befehl \u00fcberpr\u00fcft werden (in diesem Fall SSH):<\/p>\n<pre class=\"theme:dark-terminal lang:sh decode:true\">fail2ban-regex \/var\/log\/auth.log \/etc\/fail2ban\/filter.d\/sshd.conf\r\n<\/pre>\n<hr \/>\n<p><strong><em><a href=\"#overview\">Zur\u00fcck zur \u00dcbersicht<\/a><\/em><\/strong><\/p>\n<hr \/>\n<h2 id=\"Manuelle IP-Sperre via Blacklist\">Manuelle IP-Sperre via Blacklist<a id=\"Manuelle_IP-Sperre_via_Blacklist\"><\/a><\/h2>\n<p>Je nach Anwendungsfall kann es notwendig sein, bestimmte IP-Adressen in Fail2Ban manuell zu sperren. Um die \u00dcbersicht zu erhalten und die Pflege der Eintr\u00e4ge so einfach wie m\u00f6glich zu halten, empfiehlt sich eine Blacklist Datei.<\/p>\n<p>Eine eigens f\u00fcr diesen Zweck erstellte L\u00f6sung kommt an der Stelle zum Einsatz: IP-Datens\u00e4tze werden aus der angelegten Datei <em>ip.blacklist<\/em> extrahiert und in der Firewall eingetragen. Einrichten einer <a href=\"http:\/\/cup.wpcoder.de\/fail2ban-ip-blacklist\/\">Firewall-Blacklist mit Fail2Ban<\/a>.<\/p>\n<hr \/>\n<p><strong><em><a href=\"#overview\">Zur\u00fcck zur \u00dcbersicht<\/a><\/em><\/strong><\/p>\n<hr \/>\n<h2>Fail2Ban E-Mail Support<a id=\"Fail2Ban_Email_Support\"><\/a><\/h2>\n<p>Voraussetzung f\u00fcr das automatische Versenden von E-Mails ist ein installierter und konfigurierter Mailtransportagent (MTA) wie z.B. <a title=\"Postfix Email server einrichten\" href=\"http:\/\/speefak.spdns.de\/oss_lifestyle\/postfix-email-server-einrichten\/\" target=\"_blank\" rel=\"noopener noreferrer\">Postfix<\/a>.<\/p>\n<p>Fail2Ban E-Mail Funktion<br \/>\nFail2ban kann mit einigen Parametern eigenst\u00e4ndig E-Mails versenden ( IP-Adresse gesperrt, Fail2ban start\/stop etc. ). Dazu wird die Datei <strong>\/etc\/fail2ban\/jail.local<\/strong> angepasst. Der Parametereintrag &#8220;destemail = &lt;youremail.address&gt;&#8221; sollte auf eine g\u00fcltige\/n E-Mail-Adresse oder einen Systembenutzer verweisen:<\/p>\n<pre class=\"theme:dark-terminal lang:sh decode:true\">destemail = root@localhost<\/pre>\n<p>Der Parametereintrag &#8220;action = %(action_XXX)s&#8221; legt fest in welchem Umfang fail2ban Mails versendet.<\/p>\n<pre class=\"theme:dark-terminal lang:sh decode:true\">action = %(action_mw)s<\/pre>\n<p>ggf. muss der Systemmailadresse &#8220;fail2ban@&lt;hostname&gt;&#8221; noch eine g\u00fcltige Absenderadresse zugewiesen werden. Entweder direkt in der \/etc\/postfix\/sender_canonical (Fail2ban@&lt;hostname&gt; &lt;address&gt;@&lt;provider&gt;.&lt;tld&gt;) oder in der \/etc\/postfix\/generic (Fail2ban@&lt;hostname&gt; &lt;address&gt;@&lt;provider&gt;.&lt;tld&gt;). Hierbei das Neuerstellen der Postfixdatenbanken nicht vergessen.<\/p>\n<pre class=\"theme:dark-terminal lang:sh decode:true\">cd \/etc\/postfix &amp;&amp; sudo postmap generic &amp;&amp; sudo postmap sender_canonical<\/pre>\n<hr \/>\n<p>Fail2Ban E-Mail Filter Script<\/p>\n<p>Die o.g. L\u00f6sung veranlasst Fail2Ban nach jeder Aktion eine E-Mail Benachrichtigung zu versenden. Dies kann u.U. einen sehr hohen E-Mailverkehr verursachen und \/ oder das E-Mail-Postfach \u00fcberfluten. Eleganter ist es, die Fail2Ban Logs nach Eintr\u00e4gen zu durchsuchen, zu filtern und t\u00e4glich eine Zusammenfassung per E-Mail zu versenden. Folgendes Script durchsucht die Fail2Ban Logs der letzten 24 Stunden nach SSH und FTP Bans, sortiert diese und versendet das Ergebnis per E-Mail. \u00dcber einen Cronjob kann festgelegt werden, wann und wie oft das Script gestartet wird.<\/p>\n<pre class=\"theme:dark-terminal height-set:true height:150 lang:sh decode:true\">#!\/bin\/bash\r\n# name          : mail_log_report.sh\r\n# desciption    : send logfile summaries via mail\r\n# autor         : speefak ( itoss@gmx.de )\r\n# licence       : (CC) BY-NC-SA\r\n# version \t: 2.6\r\n# notice \t: requires iptables-blacklist version 2.0 or later\r\n#------------------------------------------------------------------------------------------------------------\r\n############################################################################################################\r\n###########################################   define variables   ###########################################\r\n############################################################################################################\r\n#------------------------------------------------------------------------------------------------------------\r\n\r\n ScriptName=$(basename $0)\r\n Version=$(cat $0 | grep \"# version\" | head -n1 | awk -F \":\" '{print $2}' | sed 's\/ \/\/g')\r\n MailAddress=root\t\t\t\t\t\t\t\t\t\t\t# mail address or systemuser ( requires active MTA )\r\n\r\n#------------------------------------------------------------------------------------------------------------\r\n############################################################################################################\r\n#########################################   adjustable functions   #########################################\r\n############################################################################################################\r\n#------------------------------------------------------------------------------------------------------------------------------------------------\r\nservice.ssh () {\t\t\t\t\t\t\t\t\t\t\t# add any charater (e.g. space) at beginning line to deactivate service\r\n \t\t\t\t\t\t\t\t\t\t\t\t\t# filter successfull ssh logins from \/var\/log\/auth.log and send daily summary via mail to root\r\n ServiceName=SSH\t\t\t\t\t\t\t\t\t\t\t# sevicename\r\n ServiceFilter=\"sshd\"\t\t\t\t\t\t\t\t\t\t\t# daemonname\r\n SectionFilter=\"publickey password\"\t\t\t\t\t\t\t\t\t# section expression filter\r\n LogfileSource=$(journalctl --since \"24 hour ago\" -u ssh.service)\t\t\t\t\t# journald and timeframe ( 24 hour ago )\r\n#LogfileSource=\"\/var\/log\/auth.log \/var\/log\/auth.log.1\"\t\t\t\t\t\t\t# rsyslog path to log file(s) - ( \/var\/log\/auth.log* for long check periods )\r\n MailSubjectLine=\"Daily report from $(hostname) ( $(date '+%F %H:%M') ) =&gt; Accepted SSH Logins &lt;=\"\t# Email Subject line\r\n SummaryMessage=\" Accepted SSH Logins\"\t\t\t\t\t\t\t\t\t# Email content summary line\r\n FilterPeriod=86400\t\t\t\t\t\t\t\t\t\t\t# filter past period in seconds  (86400 = 1 Day)\r\n SummaryFirstLastEntryOnTop=last\t\t\t\t\t\t\t\t\t# show &lt;first|last&gt; log entry on summary top\r\n #TODO RecapColumn =&gt; sortierungs spalte f\u00fcr doppelte eintr\u00e4ge\r\n CountDuplicateLines=false\t\t\t\t\t\t\t\t\t\t# count duplicate entries\r\n RecapDuplicateLines=false\t\t\t\t\t\t\t\t\t\t# sammurize duplicate entries\r\n MailSubjectLineSubstitutions=\"password;PW publickey;PK\" \t\t\t\t\t\t# set substitutions for mail subject line\r\n\r\n\t# filter logfile for output expressions ( date string required )\r\n\t# start line using date format : e.g. \"Jan 18 07:00:00 \" or \"2018 01-01 07:00:00 \" or \"2019-01-18 21:34:34  \" ; date divider: third space character\r\n\r\n\tlogfile_filter_service () {\r\n\t\techo \"$LogfileSource\" | grep Accepted | awk -F \": RSA\" '{printf $1 \"\\n\"}'\t\t\t\t# journald logging\r\n#\t\tzgrep -ahwEi \"$ServiceFilter\" $LogfileSource | grep Accepted | awk -F \": RSA\" '{printf $1 \"\\n\"}'\t# rsyslog logging\r\n\t}\r\n}\r\n#------------------------------------------------------------------------------------------------------------------------------------------------\r\nservice.fail2ban () {\r\n # filter via fail2ban banned IPs from \/var\/log\r\n ServiceName=Fail2Ban\t\t\t\t\t\t\t\t\t\t\t# sevicename\r\n ServiceFilter=\" Ban\"\t\t\t\t\t\t\t\t\t\t\t# daemonname \/ logfile entry\r\n SectionFilter=\"ssh wordpress nextcloud ftp http\"\t\t\t\t\t\t\t# section expression filter\r\n#LogfileSource=$(journalctl --since \"24 hour ago\" -u fail2ban.service)\t\t\t\t\t# journald unit and timeframe ( 24 hour ago ), f2ban does not write bans to journald\r\n LogfileSource=\"\/var\/log\/fail2ban.log*\"\t#TODO set filter for last gz file\t\t\t\t# path to log file(s) - ( also gz compressed files)\r\n MailSubjectLine=\"Daily report from $(hostname) ( $(date '+%F %H:%M') ) =&gt; Fail2Ban log &lt;=\"\t\t# Email Subject line\r\n SummaryMessage=\" Baned IPs \/ Attempts\"\t\t\t\t\t\t\t\t\t# Email content summary line\r\n FilterPeriod=86400\t\t\t\t\t\t\t\t\t\t\t# filter past period in seconds (86400 = 1 Day)\r\n SummaryFirstLastEntryOnTop=last\t\t\t\t\t\t\t\t\t# show &lt;first|last&gt; log entry on summary top\r\n #TODO RecapColumn =&gt; sortierungs spalte f\u00fcr doppelte eintr\u00e4ge\r\n CountDuplicateLines=true\t\t\t\t\t\t\t\t\t\t# count duplicate entries\r\n RecapDuplicateLines=true\t\t\t\t\t\t\t\t\t\t# sammurize duplicate entries\r\n MailSubjectLineSubstitutions=\"\" \t\t\t\t\t\t\t\t\t# set substitutions for mail subject line\r\n\r\n\r\n\t# filter logfile for output expressions ( date string required )\r\n\t# start line using date format : e.g. \"Jan 18 07:00:00 \" or \"2018 01-01 07:00:00 \" or \"2019-01-18 21:34:34  \" ; date divider: third space character\r\n\r\n\tlogfile_filter_service () {\r\n#\t\tif   [[ $(cat \/etc\/*release* | grep VERSION_ID | cut -d '\"' -f2) -ge 12 ]]; then\t\t\t# debian 12 or newer \/ journald does not save bans to journald\r\n#\t\t\techo \"$LogfileSource\" | cut -d \" \" -f1,2,14,15,16  | sed 's\/,...\/ \/'\r\n#\t\tel\r\n\t\tif [[ $(cat \/etc\/*release* | grep VERSION_ID | cut -d '\"' -f2) -ge 9 ]]; then\t\t\t\t# debian 9 or newer\r\n\t\t\tzgrep -ahwEi \"$ServiceFilter\" $LogfileSource | cut -d \" \" -f1,2,14,15,16  | sed 's\/,...\/ \/'\r\n\t\telif [[ $(cat \/etc\/*release* | grep VERSION_ID | cut -d '\"' -f2) == 8 ]]; then\t\t\t\t# debian 8\r\n\t\t\tzgrep -ahwEi \"$ServiceFilter\" $LogfileSource | cut -d \" \" -f1,2,5,6,7  | sed 's\/,...\/ \/'\r\n\t\tfi\r\n\t}\r\n}\r\n#------------------------------------------------------------------------------------------------------------------------------------------------\r\nexecute_post_report_command () {\r\n\tif [[ $ServiceName == \"Fail2Ban\" ]]; then\r\n\t\t# add multible bans to permanent blacklist using ipb command\r\n\t\tMaxEntries=2\r\n\t\tBlacklistedIPs=$(grep -w \"\\[sshd\\] Ban\" &lt;&lt;&lt; $ReportContent | awk '{ if ($1 &gt;= '$MaxEntries') print $0 }' | grep -Eo '[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}')\r\n\r\n\t\t# check for non empty BlacklistedIPs var\r\n\t\tif [[ -n \"$BlacklistedIPs\" ]]; then\r\n\t\t\tprintf \"\\r adding blacklisted IPs to blacklist ( ipb -a $BlacklistedIPs ) \\n\"\r\n\t\t\tipb -a $(echo \"$BlacklistedIPs\" | tr \"\\n\" \" \")\r\n\t\telse\r\n\t\t\tprintf \"\\r no new blacklisted IPs detected \\n\"\r\n\t\tfi\r\n\tfi\r\n}\r\n#------------------------------------------------------------------------------------------------------------------------------------------------\r\n############################################################################################################\r\n########################################   set vars from options  ##########################################\r\n############################################################################################################\r\n#------------------------------------------------------------------------------------------------------------\r\n\r\n\tOptionVarList=\"\r\n\r\n\t\tMailReport;-mr\r\n\t\tPrintReport;-pr\r\n\t\tExecutePostReportCommands;-eprc\r\n\t\tMonochrome;-m\r\n\t\tScriptInformation;-si\r\n\t\"\r\n\r\n\t# set entered vars from optionvarlist\r\n\tfor InputOption in $(echo \" $@\" | tr \" \" \"\\n\" ) ; do\r\n\r\n\t\tfor VarNameVarValue in $OptionVarList ; do\r\n\r\n\t\t\tVarName=$(echo \"$VarNameVarValue\" | cut -d \";\" -f1)\r\n\t\t\tVarValue=$(echo \"$VarNameVarValue\" | cut -d \";\" -f2)\r\n\r\n\t\t\tif [[ $InputOption == $VarValue ]]; then\r\n\t\t\t\teval $(echo \"$VarName\"=\"$InputOption\")\r\n\t\t\tfi\r\n\t\tdone\r\n\tdone\r\n\r\n#------------------------------------------------------------------------------------------------------------------------------------------------\r\n############################################################################################################\r\n###########################################   fixed functions   ############################################\r\n############################################################################################################\r\n#------------------------------------------------------------------------------------------------------------\r\nload_color_codes () {\r\n\tBlack='\\033[0;30m'\t&amp;&amp;\tDGray='\\033[1;30m'\r\n\tLRed='\\033[0;31m'\t&amp;&amp;\tRed='\\033[1;31m'\r\n\tLGreen='\\033[0;32m'\t&amp;&amp;\tGreen='\\033[1;32m'\r\n\tLYellow='\\033[0;33m'\t&amp;&amp;\tYellow='\\033[1;33m'\r\n\tLBlue='\\033[0;34m'\t&amp;&amp;\tBlue='\\033[1;34m'\r\n\tLPurple='\\033[0;35m'\t&amp;&amp;\tPurple='\\033[1;35m'\r\n\tLCyan='\\033[0;36m'\t&amp;&amp;\tCyan='\\033[1;36m'\r\n\tLLGrey='\\033[0;37m'\t&amp;&amp;\tWhite='\\033[1;37m'\r\n\tReset='\\033[0m'\r\n\t# Use them to print in your required colours:\r\n\t# printf \"%s\\n\" \"Text in ${Red}red${Reset}, white and ${Blue}blue${Reset}.\"\r\n\r\n\tBG='\\033[47m'\r\n\tFG='\\033[0;30m'\r\n\r\n\t# reloard colored global vars\r\n\tfor i in $(cat $0 | sed '\/load_color_codes\/q'  | grep '${Reset}'); do\r\n\t\teval \"$i\"\r\n\tdone\r\n}\r\n#------------------------------------------------------------------------------------------------------------------------------------------------\r\nusage() {\r\n\tprintf \" iptables-blacklist version: $Version | script location $basename $0\\n\"\r\n\tclear\r\n\tprintf \"\\n\"\r\n\tprintf \" Usage: $(basename $0) &lt;options&gt; \"\r\n\tprintf \"\\n\"\r\n\tprintf \" -h\t\t=&gt; help dialog \\n\"\r\n\tprintf \" -stm\t\t=&gt; send test mail\\n\"\r\n\tprintf \" -mr\t\t=&gt; mail report \\n\"\r\n\tprintf \" -pr\t\t=&gt; print report \\n\"\r\n\tprintf \" -eprc\t\t=&gt; execute post report commands \\n\"\r\n\tprintf \" -m\t\t=&gt; monochrome output \\n\"\r\n\tprintf \" -si\t\t=&gt; show script information \\n\"\r\n\tprintf  \"\\n${Red} $1 ${Reset}\\n\"\r\n\tprintf \"\\n\"\r\n\texit\r\n}\r\n#------------------------------------------------------------------------------------------------------------\r\nscript_information () {\r\n\tprintf \"\\n\"\r\n\tprintf \" Scriptname: $ScriptName\\n\"\r\n\tprintf \" Version:    $Version \\n\"\r\n\tprintf \" Location:   $(pwd)\/$ScriptName\\n\"\r\n\tprintf \" Filesize:   $(ls -lh $0 | cut -d \" \" -f5)\\n\"\r\n\tprintf \"\\n\"\r\n\texit 0\r\n}\r\n#------------------------------------------------------------------------------------------------------------------------------------------------\r\nlogfile_entry_filter () {\r\n\r\n\t# set unixtime beginn past period\r\n\tUnixtimePastValue=$(($(date +%s)-$FilterPeriod))\r\n\r\n\tLogfileEntries=$(logfile_filter_service)\r\n\tLogfileEntriesCount=$( wc -l &lt;&lt;&lt; $LogfileEntries)\r\n\tCounter=1\t\t\t\t\t\t\t\t\t\t\t# ab Debian 10 =&gt; counter=1\r\n\r\n\t# compare timestamp and print matched logfile line\r\n\tSAVEIFS=$IFS\r\n\tIFS=$(echo -en \"\\n\\b\")\r\n\tfor LogEntry in $LogfileEntries ;do\r\n\r\n\t\t# skip counter for cron execution\r\n\t\tif [[ ! $CronExecution == true ]]; then\r\n\t\t\tprintf \"\\r processing entry $Counter\/$LogfileEntriesCount\" &gt;&amp;2\r\n\t\t\tCounter=$((Counter+1))\r\n\t\tfi\r\n\r\n\t\t# skip Dec entries for turn of the year\r\n\t\tif [[ $TurOfTheYear == true ]] || [[ -n $( grep \"^Jan \" &lt;&lt;&lt; $LogEntry ) ]]; then\r\n\t\t\tTurOfTheYear=true\r\n\t\t\tif [[ $( grep \"^Dec \" &lt;&lt;&lt; $LogEntry ) ]]; then\r\n\t\t\t\tcontinue\r\n\t\t\tfi\r\n\t\tfi\r\n\r\n\t\tif [[ $UnixtimePastValue -lt $(date -d \"$(echo $LogEntry | cut -d \" \" -f1-3)\" +\"%s\") ]]; then \t\t\t\t\t# divider : third space to get time string,faster\r\n\t\t#if [[ $UnixtimePastValue -lt $(date -d \"$(echo $LogEntry | sed 's\/\\([0-9]\\{2\\}:\\)\\{2\\}[0-9]\\{2\\}.*$\/\/')\" +\"%s\") ]]; then\t# divider : \"01:00:00\" to get time string\r\n\t\t\tLogfileFilteredDateContent=$(echo -e \"$LogfileFilteredDateContent \\n $LogEntry\")\r\n\t\tfi\r\n\tdone\r\n\tIFS=$SAVEIFS\r\n\r\n\t# print logfile content for each filter string\r\n\tfor SectionFilterLine in $SectionFilter ;do\r\n\r\n\t\t# filter log entries and write to proccessing var\r\n\t\tFinalLogfileContent=$(printf \"$(echo \"$LogfileFilteredDateContent\" | grep $SectionFilterLine | sort -rnk1)\")\r\n\t\tFinalLogfileContentRecaped=$(printf \"$(echo \"$LogfileFilteredDateContent\" | grep $SectionFilterLine | sort -k4 | uniq -f3 -c | sort -rnk1)\") # TODO  uniq -f3 -c =&gt;  uniq -f$VAR -c\r\n\r\n\t\t# set counter\r\n\t\tFinalLogfileContentCounter=$(echo \"$FinalLogfileContent\" | grep $SectionFilterLine |  sed  '\/^ $\/d'  | grep -c .)\r\n\t\tFinalLogfileContentRecapedCounter=$(echo \"$FinalLogfileContentRecaped\" | grep $SectionFilterLine |  sed  '\/^ $\/d'  | grep -c .)\r\n\r\n\t\t# set output sequence\r\n\t\tSummaryFirstLastEntryOnTop=$(echo $SummaryFirstLastEntryOnTop | sed 's\/last\/tee\/' | sed 's\/first\/tac\/')\r\n\r\n\t\t# print counter and logentries for each section expression filter\r\n\t\tif   [[ $CountDuplicateLines == true ]] &amp;&amp; [[ $RecapDuplicateLines == true ]]; then\r\n\t\t\tprintf \"$SummaryMessage [$SectionFilterLine] =&gt; $FinalLogfileContentRecapedCounter \/ $FinalLogfileContentCounter \\n\\n\"\r\n\t\t\tprintf \"$FinalLogfileContentRecaped\\n\" | $SummaryFirstLastEntryOnTop | sed '\/^$\/d'\r\n\r\n\t\telif [[ $CountDuplicateLines == true ]] &amp;&amp; [[ $RecapDuplicateLines == false ]]; then\r\n\t\t\tprintf \"$SummaryMessage [$SectionFilterLine] =&gt; $FinalLogfileContentRecapedCounter \/ $FinalLogfileContentCounter \\n\\n\"\r\n\t\t\tprintf \"$FinalLogfileContent\\n\" | $SummaryFirstLastEntryOnTop | sed '\/^$\/d'\r\n\r\n\t\telif [[ $CountDuplicateLines == false ]] &amp;&amp; [[ $RecapDuplicateLines == true ]]; then\r\n\t\t\tprintf \"$SummaryMessage [$SectionFilterLine] =&gt; $FinalLogfileContentRecapedCounter \\n\\n\"\r\n\t\t\tprintf \"$FinalLogfileContentRecaped\\n\" | $SummaryFirstLastEntryOnTop | sed '\/^$\/d'\r\n\r\n\t\telif [[ $CountDuplicateLines == false ]] &amp;&amp; [[ $RecapDuplicateLines == false ]]; then\r\n\t\t\tprintf \"$SummaryMessage [$SectionFilterLine] =&gt; $FinalLogfileContentRecapedCounter \\n\\n\"\r\n\t\t\tprintf \"$FinalLogfileContent\\n\" | $SummaryFirstLastEntryOnTop | sed '\/^$\/d'\r\n\t\tfi\r\n\r\n\t\tif [[ -n $FinalLogfileContent ]]; then\r\n\t\t\tprintf \"\\n\"\r\n\t\tfi\r\n\tdone\r\n\r\n\tprintf \"End of Report \\n\\n \"\r\n}\r\n\r\n#------------------------------------------------------------------------------------------------------------------------------------------------\r\n############################################################################################################\r\n#############################################   start script   #############################################\r\n############################################################################################################\r\n#------------------------------------------------------------------------------------------------------------------------------------------------\r\n\r\n\t# check for cronjob execution and cronjob options\r\n\tCronExecution=\r\n\tif [ -z $(grep \"\/\" &lt;&lt;&lt; \"$(tty)\") ]; then\r\n\t\tCronExecution=true\r\n\t\tMonochrome=true\r\n\t\tTERM=xterm-256color\r\n# \t\tTERM=linux\r\n\t\texport TERM \r\n\tfi\r\n\r\n#------------------------------------------------------------------------------------------------------------------------------------------------\r\n\r\n\t# check for help dialog\r\n\tif [[ -z $1 ]] || [[ $1 == -h ]]; then usage ;fi\r\n\r\n#------------------------------------------------------------------------------------------------------------------------------------------------\r\n\r\n\t# check for monochrome output\r\n\tif [[ -z $Monochrome ]]; then\r\n\t\tload_color_codes\r\n\tfi\r\n\r\n#------------------------------------------------------------------------------------------------------------------------------------------------\r\n\r\n\t# check for script information\r\n\tif [[ -n $ScriptInformation ]]; then script_information ; fi\r\n\r\n#------------------------------------------------------------------------------------------------------------------------------------------------\r\n\r\n\t# check for root permission\r\n\tif [ \"$(whoami)\" = \"root\" ]; then echo \"\";else echo \"Are You Root ?\";exit 1;fi\r\n\r\n#------------------------------------------------------------------------------------------------------------------------------------------------\r\n\r\n\t# check input options\r\n\tif [[ -z $@ ]] || [[ $@ == -[hH] ]]; then usage \"help dialog\" ; fi\r\n\r\n\tif [[ -n $(grep stm &lt;&lt;&lt; $@) ]]; then\r\n\t\tprintf \"execute: printf \\\"mail_log_report testmail on $(date) from $(hostname)\\\" | mail -s \\\"testmail\\\" $MailAddress \\n\"\r\n\t\tprintf \"mail_log_report testmail on $(date) from $(hostname)\" | mail -s \"testmail\" $MailAddress\r\n\t\texit\r\n\tfi\r\n\r\n\tif [[ $(grep -c . &lt;&lt;&lt; $MailReport$PrintReport$ExecutePostReportCommands) == 0 ]]; then\r\n\t\tusage \" missing options \"\r\n\tfi\r\n\r\n#------------------------------------------------------------------------------------------------------------------------------------------------\r\n\r\n\t# processing services ( service.&lt;name&gt; functions )\r\n\tfor service in $(cat $0 | grep \"() {\" | grep \"^service\\.\" | cut -d \" \" -f1 ); do\r\n\r\n\t\t# execute service section to set service vars\r\n\t\t$service\r\n\r\n\t\tprintf \"\\n analyzing log files: $LogfileSource ($ServiceName) ... \\n\"\r\n\r\n\t\t# create ReportContent from filtered log entries and calculate counter\r\n\t\tReportContent=$(logfile_entry_filter)\r\n\r\n\t\t# set summary counter\r\n\t\tCounterSummary=$(for SectionFilterLine in $SectionFilter ;do\r\n\t\t\t\t\tCounter=$(echo \"$ReportContent\" | grep -w \"\\[$SectionFilterLine\\]\" | awk -F \"=&gt;\" '{printf $2}' | sed 's\/ \/\/g')\r\n\t\t\t\t\tprintf \"$SectionFilterLine $Counter, \"\r\n\t\t\t\tdone\r\n\t\t\t\tprintf \"\\n\\n\" )\r\n\r\n\t\tif [[ -n $MailReport ]]; then\r\n\t\t\t# set subject line\r\n\t\t\tMailSubjectLine=\"$MailSubjectLine $CounterSummary\"\r\n\r\n\t\t\t# set mail summary header\r\n\t\t\tMailContentHeaderLine=\"$MailSubjectLine $(date -d \"$FilterPeriod seconds ago\" \"+%F|%H:%M:%H\") - $(date  \"+%F|%H:%M:%H\")\"\r\n\r\n\t\t\t# parse mail subject for shortnames\r\n\t\t\tfor i in $MailSubjectLineSubstitutions ;do\r\n\t\t\t\tBaseExpression=$(echo $i | cut -d \";\" -f1)\r\n\t\t\t\tOverwriteExpression=$(echo $i | cut -d \";\" -f2)\r\n\t\t\t\tMailSubjectLine=$(echo \"$MailSubjectLine\" | sed 's\/'$BaseExpression'\/'$OverwriteExpression'\/' )\r\n\t\t\tdone\r\n\r\n\t\t\t# send report via mail\r\n\t\t\tprintf \"$MailContentHeaderLine \\n\\n$ReportContent\" | mail -a \"Content-Type: text\/plain\" -s \"$MailSubjectLine\" $MailAddress\r\n\t\tfi\r\n\r\n\t\tif [[ -n $PrintReport ]]; then\r\n\t\t\t# print report only\r\n\t\t\tprintf \"\\n\\n$ReportContent\"\r\n\t\tfi\r\n\r\n\r\n\t\tif [[ -n $ExecutePostReportCommands ]]; then\r\n\t\t\t# execute post report functions\r\n\t\t\texecute_post_report_command\r\n\t\tfi\r\n\tdone\r\n\r\n#------------------------------------------------------------------------------------------------------------------------------------------------\r\n\r\nexit 0\r\n\r\n------------------------------------------------------------------------------------------------------------\r\n############################################################################################################\r\n##############################################   changelog   ###############################################\r\n############################################################################################################\r\n#------------------------------------------------------------------------------------------------------------\r\n\r\n#changelog 2.5 =&gt; 2.6 : add journald logfile analyzing for ssh deamon\r\n<\/pre>\n<address>\n<hr \/>\n<p style=\"text-align: center;\"><strong><em><a href=\"#overview\">Zur\u00fcck zur \u00dcbersicht<\/a><\/em><\/strong><\/p>\n<address>\n<hr \/>\n<\/address>\n<\/address>\n<h2 style=\"text-align: left;\">Fail2ban steuern<a id=\"Fail2ban_steuern\"><\/a><\/h2>\n<p>Fail2Ban nutzt eine eigene Logdatei ( \/var\/log\/fail2ban.log ) in der alle relevanten Aktionen protokliert werden.<\/p>\n<hr \/>\n<p>Der Status der verschiedenen Jails kann wie filgt abgerufen werden:<\/p>\n<pre class=\"lang:default decode:true \">fail2ban-client status &lt;jailname&gt;<\/pre>\n<hr \/>\n<p>IP-Adresse manuell entsperren:<\/p>\n<p>Aufgrund welchen Jails die Adresse gesperrt wurde kann \u00fcber die\u00a0 Fail2ban Logfiles auslesen werden :<\/p>\n<pre class=\"theme:dark-terminal lang:sh decode:true \">cat \/var\/log\/fail2ban.log | grep xxx.xxx.xxx.xxx<\/pre>\n<p>Mit der Jail Information wird dann die IP Adresse mit dem Fail2ban Client entsperrt :<\/p>\n<pre class=\"theme:dark-terminal lang:sh decode:true\">fail2ban-client set ssh unbanip xxx.xxx.xxx.xxx<\/pre>\n<p>Alternativ kann die IP auch direkt \u00fcber iptables wieder freigeben werden. Dazu wird die Iptables Chain und die Nummer der IP in der Chain ben\u00f6tigt :<\/p>\n<pre class=\"theme:dark-terminal lang:sh decode:true\">iptables -L -n --line-numbers<\/pre>\n<p>Hat man die betreffenden Informationen zu der IP gefunden wir die IP direkt \u00fcber Iptables freigeben :<\/p>\n<pre class=\"theme:dark-terminal lang:sh decode:true \">iptables -D fail2ban-ssh 1<\/pre>\n<hr \/>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" wp-image-2821 alignleft\" src=\"https:\/\/speefak.spdns.de\/oss_lifestyle\/wp-content\/uploads\/2014\/08\/CC_BY_NC_SA.png\" alt=\"CC_BY_NC_SA\" width=\"65\" height=\"23\" \/><span style=\"font-size: 10pt;\">by Speefak<span style=\"font-size: 8pt;\"> | <a href=\"https:\/\/www.my-it-brain.de\/wordpress\/wordpress-mit-fail2ban-vor-brute-force-angriffen-schuetzen\/\">www.my-it-brain.de<\/a><\/span><\/span><span style=\"font-size: 8pt;\">\u00a0|\u00a0 <a href=\"http:\/\/www.the-art-of-web.com\/system\/fail2ban-log\/\" target=\"_blank\" rel=\"noopener noreferrer\">the-art-of-web.com<\/a>\u00a0| <a href=\"http:\/\/www.the-art-of-web.com\/system\/fail2ban-sendmail\/\" target=\"_blank\" rel=\"noopener noreferrer\">the-art-of-web.com<\/a>\u00a0| <a href=\"http:\/\/www.the-art-of-web.com\/system\/fail2ban\/\" target=\"_blank\" rel=\"noopener noreferrer\">the-art-of-web.com<\/a>\u00a0| <a href=\"http:\/\/www.the-art-of-web.com\/system\/block-ftp-hacking\/\" target=\"_blank\" rel=\"noopener noreferrer\">the-art-of-web.com<\/a>\u00a0| <a href=\"https:\/\/www.w2k.ch\/blog\/wordpress-mit-fail2ban-absichern\/#comment-211\">www.w2k.ch<\/a><\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Fail2Ban ist eine auf Python basierte Skriptsammlung f\u00fcr Linux Server und Systeme, die es Administratoren erm\u00f6glicht, die Sicherheit ihres Systems zu erh\u00f6hen und sich vor Angriffen zu sch\u00fctzen, die auf wiederholte Anmeldeversuche abzielen, indem es fehlgeschlagene Anmeldeversuche \u00fcberwacht und tempor\u00e4re Sperrma\u00dfnahmen auf IP-Adressen anwendet, die verd\u00e4chtige oder b\u00f6sartige Aktivit\u00e4ten zeigen. Da zu z\u00e4hlen: Schutz vor [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8,26,32,40,43],"tags":[],"class_list":["post-2546","post","type-post","status-publish","format-standard","hentry","category-anleitungen","category-linux","category-netzwerke","category-server","category-sicherheit"],"rttpg_featured_image_url":null,"rttpg_author":{"display_name":"speefak","author_link":"https:\/\/speefak.spdns.de\/oss_lifestyle\/author\/speefak_oss\/"},"rttpg_comment":0,"rttpg_category":"<a href=\"https:\/\/speefak.spdns.de\/oss_lifestyle\/category\/anleitungen\/\" rel=\"category tag\">Anleitungen<\/a> <a href=\"https:\/\/speefak.spdns.de\/oss_lifestyle\/category\/linux\/\" rel=\"category tag\">Linux<\/a> <a href=\"https:\/\/speefak.spdns.de\/oss_lifestyle\/category\/netzwerke\/\" rel=\"category tag\">Netzwerke<\/a> <a href=\"https:\/\/speefak.spdns.de\/oss_lifestyle\/category\/server\/\" rel=\"category tag\">Server<\/a> <a href=\"https:\/\/speefak.spdns.de\/oss_lifestyle\/category\/sicherheit\/\" rel=\"category tag\">Sicherheit<\/a>","rttpg_excerpt":"Fail2Ban ist eine auf Python basierte Skriptsammlung f\u00fcr Linux Server und Systeme, die es Administratoren erm\u00f6glicht, die Sicherheit ihres Systems zu erh\u00f6hen und sich vor Angriffen zu sch\u00fctzen, die auf wiederholte Anmeldeversuche abzielen, indem es fehlgeschlagene Anmeldeversuche \u00fcberwacht und tempor\u00e4re Sperrma\u00dfnahmen auf IP-Adressen anwendet, die verd\u00e4chtige oder b\u00f6sartige Aktivit\u00e4ten zeigen. Da zu z\u00e4hlen: Schutz vor&hellip;","_links":{"self":[{"href":"https:\/\/speefak.spdns.de\/oss_lifestyle\/wp-json\/wp\/v2\/posts\/2546","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/speefak.spdns.de\/oss_lifestyle\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/speefak.spdns.de\/oss_lifestyle\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/speefak.spdns.de\/oss_lifestyle\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/speefak.spdns.de\/oss_lifestyle\/wp-json\/wp\/v2\/comments?post=2546"}],"version-history":[{"count":0,"href":"https:\/\/speefak.spdns.de\/oss_lifestyle\/wp-json\/wp\/v2\/posts\/2546\/revisions"}],"wp:attachment":[{"href":"https:\/\/speefak.spdns.de\/oss_lifestyle\/wp-json\/wp\/v2\/media?parent=2546"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/speefak.spdns.de\/oss_lifestyle\/wp-json\/wp\/v2\/categories?post=2546"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/speefak.spdns.de\/oss_lifestyle\/wp-json\/wp\/v2\/tags?post=2546"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}