From 112b5b91647c3dea45cc1c9bc364df526c8012f1 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 26 Jan 2022 19:05:15 +0100 Subject: Merging upstream version 1.33.0. Signed-off-by: Daniel Baumann --- collectors/python.d.plugin/fail2ban/README.md | 59 ++++++++++++++++++---- .../python.d.plugin/fail2ban/fail2ban.chart.py | 57 +++++++++++++-------- 2 files changed, 85 insertions(+), 31 deletions(-) (limited to 'collectors/python.d.plugin/fail2ban') diff --git a/collectors/python.d.plugin/fail2ban/README.md b/collectors/python.d.plugin/fail2ban/README.md index c1ad994a5..90a59dce0 100644 --- a/collectors/python.d.plugin/fail2ban/README.md +++ b/collectors/python.d.plugin/fail2ban/README.md @@ -10,14 +10,55 @@ Monitors the fail2ban log file to show all bans for all active jails. ## Requirements -- fail2ban.log file MUST BE readable by Netdata (A good idea is to add **create 0640 root netdata** to fail2ban conf at logrotate.d) +The `fail2ban.log` file must be readable by the user `netdata`: -It produces one chart with multiple lines (one line per jail) +- change the file ownership and access permissions. +- update `/etc/logrotate.d/fail2ban` to persists the changes after rotating the log file. + +
+ Click to expand the instruction. + +To change the file ownership and access permissions, execute the following: + +```shell +sudo chown root:netdata /var/log/fail2ban.log +sudo chmod 640 /var/log/fail2ban.log +``` + +To persist the changes after rotating the log file, add `create 640 root netdata` to the `/etc/logrotate.d/fail2ban`: + +```shell +/var/log/fail2ban.log { + + weekly + rotate 4 + compress + + delaycompress + missingok + postrotate + fail2ban-client flushlogs 1>/dev/null + endscript + + # If fail2ban runs as non-root it still needs to have write access + # to logfiles. + # create 640 fail2ban adm + create 640 root netdata +} +``` + +
+ +## Charts + +- Failed attempts in attempts/s +- Bans in bans/s +- Banned IP addresses (since the last restart of netdata) in ips ## Configuration -Edit the `python.d/fail2ban.conf` configuration file using `edit-config` from the Netdata [config -directory](/docs/configure/nodes.md), which is typically at `/etc/netdata`. +Edit the `python.d/fail2ban.conf` configuration file using `edit-config` from the +Netdata [config directory](/docs/configure/nodes.md), which is typically at `/etc/netdata`. ```bash cd /etc/netdata # Replace this path with your Netdata config directory, if different @@ -28,13 +69,13 @@ Sample: ```yaml local: - log_path: '/var/log/fail2ban.log' - conf_path: '/etc/fail2ban/jail.local' - exclude: 'dropbear apache' + log_path: '/var/log/fail2ban.log' + conf_path: '/etc/fail2ban/jail.local' + exclude: 'dropbear apache' ``` -If no configuration is given, module will attempt to read log file at `/var/log/fail2ban.log` and conf file at `/etc/fail2ban/jail.local`. -If conf file is not found default jail is `ssh`. +If no configuration is given, module will attempt to read log file at `/var/log/fail2ban.log` and conf file +at `/etc/fail2ban/jail.local`. If conf file is not found default jail is `ssh`. --- diff --git a/collectors/python.d.plugin/fail2ban/fail2ban.chart.py b/collectors/python.d.plugin/fail2ban/fail2ban.chart.py index 99dbf79dd..76f6d92b4 100644 --- a/collectors/python.d.plugin/fail2ban/fail2ban.chart.py +++ b/collectors/python.d.plugin/fail2ban/fail2ban.chart.py @@ -11,8 +11,9 @@ from glob import glob from bases.FrameworkServices.LogService import LogService ORDER = [ + 'jails_failed_attempts', 'jails_bans', - 'jails_in_jail', + 'jails_banned_ips', ] @@ -23,40 +24,49 @@ def charts(jails): ch = { ORDER[0]: { - 'options': [None, 'Jails Ban Rate', 'bans/s', 'bans', 'jail.bans', 'line'], + 'options': [None, 'Failed attempts', 'attempts/s', 'failed attempts', 'fail2ban.failed_attempts', 'line'], 'lines': [] }, ORDER[1]: { - 'options': [None, 'Banned IPs (since the last restart of netdata)', 'IPs', 'in jail', - 'jail.in_jail', 'line'], + 'options': [None, 'Bans', 'bans/s', 'bans', 'fail2ban.bans', 'line'], + 'lines': [] + }, + ORDER[2]: { + 'options': [None, 'Banned IP addresses (since the last restart of netdata)', 'ips', 'banned ips', + 'fail2ban.banned_ips', 'line'], 'lines': [] }, } for jail in jails: - dim = [ - jail, - jail, - 'incremental', - ] + dim = ['{0}_failed_attempts'.format(jail), jail, 'incremental'] ch[ORDER[0]]['lines'].append(dim) - dim = [ - '{0}_in_jail'.format(jail), - jail, - 'absolute', - ] + dim = [jail, jail, 'incremental'] ch[ORDER[1]]['lines'].append(dim) + dim = ['{0}_in_jail'.format(jail), jail, 'absolute'] + ch[ORDER[2]]['lines'].append(dim) + return ch RE_JAILS = re.compile(r'\[([a-zA-Z0-9_-]+)\][^\[\]]+?enabled\s+= +(true|yes|false|no)') +ACTION_BAN = 'Ban' +ACTION_UNBAN = 'Unban' +ACTION_RESTORE_BAN = 'Restore Ban' +ACTION_FOUND = 'Found' + # Example: -# 2018-09-12 11:45:53,715 fail2ban.actions[25029]: WARNING [ssh] Unban 195.201.88.33 -# 2018-09-12 11:45:58,727 fail2ban.actions[25029]: WARNING [ssh] Ban 217.59.246.27 -# 2018-09-12 11:45:58,727 fail2ban.actions[25029]: WARNING [ssh] Restore Ban 217.59.246.27 -RE_DATA = re.compile(r'\[(?P[A-Za-z-_0-9]+)\] (?PUnban|Ban|Restore Ban) (?P[a-f0-9.:]+)') +# 2018-09-12 11:45:58,727 fail2ban.actions[25029]: WARNING [ssh] Found 203.0.113.1 +# 2018-09-12 11:45:58,727 fail2ban.actions[25029]: WARNING [ssh] Ban 203.0.113.1 +# 2018-09-12 11:45:58,727 fail2ban.actions[25029]: WARNING [ssh] Restore Ban 203.0.113.1 +# 2018-09-12 11:45:53,715 fail2ban.actions[25029]: WARNING [ssh] Unban 203.0.113.1 +RE_DATA = re.compile( + r'\[(?P[A-Za-z-_0-9]+)\] (?P{0}|{1}|{2}|{3}) (?P[a-f0-9.:]+)'.format( + ACTION_BAN, ACTION_UNBAN, ACTION_RESTORE_BAN, ACTION_FOUND + ) +) DEFAULT_JAILS = [ 'ssh', @@ -94,6 +104,7 @@ class Service(LogService): self.monitoring_jails = self.jails_auto_detection() for jail in self.monitoring_jails: + self.data['{0}_failed_attempts'.format(jail)] = 0 self.data[jail] = 0 self.data['{0}_in_jail'.format(jail)] = 0 @@ -124,12 +135,14 @@ class Service(LogService): jail, action, ip = match['jail'], match['action'], match['ip'] - if action == 'Ban' or action == 'Restore Ban': + if action == ACTION_FOUND: + self.data['{0}_failed_attempts'.format(jail)] += 1 + elif action in (ACTION_BAN, ACTION_RESTORE_BAN): self.data[jail] += 1 if ip not in self.banned_ips[jail]: self.banned_ips[jail].add(ip) self.data['{0}_in_jail'.format(jail)] += 1 - else: + elif action == ACTION_UNBAN: if ip in self.banned_ips[jail]: self.banned_ips[jail].remove(ip) self.data['{0}_in_jail'.format(jail)] -= 1 @@ -196,9 +209,9 @@ class Service(LogService): if name in exclude: continue - if status in ('true','yes') and name not in active_jails: + if status in ('true', 'yes') and name not in active_jails: active_jails.append(name) - elif status in ('false','no') and name in active_jails: + elif status in ('false', 'no') and name in active_jails: active_jails.remove(name) return active_jails or DEFAULT_JAILS -- cgit v1.2.3