From e5b4042eb22f2f07263cc72650f848b9e0069348 Mon Sep 17 00:00:00 2001 From: Aleksandar Urosevic Date: Mon, 1 Sep 2025 16:06:46 +0200 Subject: [PATCH 1/8] Prevent $config flat array to be overwriten by report script --- Web-UI/includes/actions/action_report-ip.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Web-UI/includes/actions/action_report-ip.php b/Web-UI/includes/actions/action_report-ip.php index 1ee590f..f8060c7 100644 --- a/Web-UI/includes/actions/action_report-ip.php +++ b/Web-UI/includes/actions/action_report-ip.php @@ -3,10 +3,11 @@ header('Content-Type: application/json; charset=utf-8'); -$config = parse_ini_file('/opt/Fail2Ban-Report/Settings/fail2ban-report.config'); +// Read config to flat array $infoConfig (to avoid overwrite from included $script) +$infoConfig = parse_ini_file('/opt/Fail2Ban-Report/Settings/fail2ban-report.config'); $ips = $_POST['ip'] ?? null; -if (!$config['report'] || !$config['report_types'] || !$ips) { +if (!$infoConfig['report'] || !$infoConfig['report_types'] || !$ips) { echo json_encode([ 'success' => false, 'message' => 'Reporting not enabled or invalid IP(s).', @@ -19,7 +20,7 @@ $ips = [$ips]; // Convert single IP to array } -$services = array_map('trim', explode(',', $config['report_types'])); +$services = array_map('trim', explode(',', $infoConfig['report_types'])); $results = []; $allMessages = []; $overallSuccess = true; @@ -34,7 +35,7 @@ $script = __DIR__ . "/reports/$service.php"; // Check API keys for services that require them - if ($service === 'abuseipdb' && empty($config['abuseipdb_key'])) { + if ($service === 'abuseipdb' && empty($infoConfig['abuseipdb_key'])) { $ipSuccess = false; $reportResults[$service] = [ 'success' => false, @@ -43,8 +44,7 @@ ]; $messages[] = "[$service] API key missing"; continue; - } - if ($service === 'ipinfo' && empty($config['ipinfo_key'])) { + } elseif ($service === 'ipinfo' && empty($infoConfig['ipinfo_key'])) { $ipSuccess = false; $reportResults[$service] = [ 'success' => false, From 5acc201b7ca7895f3aa57402324f6ee7678ac6ee Mon Sep 17 00:00:00 2001 From: Aleksandar Urosevic Date: Mon, 1 Sep 2025 16:11:29 +0200 Subject: [PATCH 2/8] Fix: string interpolation does not directly support the null coalescing operator --- Web-UI/includes/actions/reports/ipinfo.php | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Web-UI/includes/actions/reports/ipinfo.php b/Web-UI/includes/actions/reports/ipinfo.php index bd5627d..d097e9e 100644 --- a/Web-UI/includes/actions/reports/ipinfo.php +++ b/Web-UI/includes/actions/reports/ipinfo.php @@ -1,7 +1,7 @@ true, From 90e023a742cb1c9dc398ff99046377a5820667ee Mon Sep 17 00:00:00 2001 From: Aleksandar Urosevic Date: Mon, 1 Sep 2025 16:32:11 +0200 Subject: [PATCH 3/8] Refactor: update require_once paths for consistency across action files --- Web-UI/includes/actions/action_ban-ip.php | 2 +- Web-UI/includes/actions/action_unban-ip.php | 2 +- Web-UI/includes/actions/reports/abuseipdb.php | 2 +- Web-UI/includes/list-files.php | 7 ++++--- Web-UI/includes/paths.php | 2 +- Web-UI/includes/warnings.php | 2 +- 6 files changed, 9 insertions(+), 8 deletions(-) diff --git a/Web-UI/includes/actions/action_ban-ip.php b/Web-UI/includes/actions/action_ban-ip.php index 17f9909..89f7912 100644 --- a/Web-UI/includes/actions/action_ban-ip.php +++ b/Web-UI/includes/actions/action_ban-ip.php @@ -2,7 +2,7 @@ // includes/actions/action_ban-ip.php header('Content-Type: application/json; charset=utf-8'); -require_once __DIR__ . '/../block-ip.php'; +require_once dirname(__DIR__) . '/block-ip.php'; // Check if IP(s) were provided if (!isset($_POST['ip'])) { diff --git a/Web-UI/includes/actions/action_unban-ip.php b/Web-UI/includes/actions/action_unban-ip.php index 4ff8b61..51019ee 100644 --- a/Web-UI/includes/actions/action_unban-ip.php +++ b/Web-UI/includes/actions/action_unban-ip.php @@ -3,7 +3,7 @@ header('Content-Type: application/json; charset=utf-8'); -require_once __DIR__ . '/../unblock-ip.php'; +require_once dirname(__DIR__) . '/unblock-ip.php'; // Validate input if (!isset($_POST['ip']) || !isset($_POST['jail'])) { diff --git a/Web-UI/includes/actions/reports/abuseipdb.php b/Web-UI/includes/actions/reports/abuseipdb.php index b21f956..e850d07 100644 --- a/Web-UI/includes/actions/reports/abuseipdb.php +++ b/Web-UI/includes/actions/reports/abuseipdb.php @@ -1,7 +1,7 @@ 'disabled', 'reason' => 'No config found']); exit; From e8f0fcd3e6fb405cdd9fb05a305f0541b26bfdef Mon Sep 17 00:00:00 2001 From: Aleksandar Urosevic Date: Mon, 1 Sep 2025 16:32:51 +0200 Subject: [PATCH 4/8] Add mising JS asset --- Web-UI/assets/js/ufw-report.js | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 Web-UI/assets/js/ufw-report.js diff --git a/Web-UI/assets/js/ufw-report.js b/Web-UI/assets/js/ufw-report.js new file mode 100644 index 0000000..104a2fa --- /dev/null +++ b/Web-UI/assets/js/ufw-report.js @@ -0,0 +1,30 @@ +document.addEventListener('DOMContentLoaded', () => { + async function updateUFWBlocks() { + const div = document.getElementById('ufw-blocks-info'); + if (!div) return; + + try { + const response = await fetch('includes/ufw-report.php'); + if (!response.ok) throw new Error(`Network response was not ok`); + const data = await response.json(); + + // Gesamt + let output = `Total Matches: ${data.total}`; + + // Per IP + if (data.per_ip && Object.keys(data.per_ip).length > 0) { + const ipInfo = Object.entries(data.per_ip).map(([ip, info]) => { + return `${info.blocklist}: ${ip} (${info.count})`; + }); + output += ' | ' + ipInfo.join(' | '); + } + + div.textContent = output; + } catch (err) { + console.error('Error fetching UFW blocklist data:', err); + div.textContent = '⚠ Error loading UFW blocklist info'; + } + } + + updateUFWBlocks(); +}); From ddc106c5da1e4a4f7cca75845184d07462ec8271 Mon Sep 17 00:00:00 2001 From: Aleksandar Urosevic Date: Mon, 1 Sep 2025 16:49:36 +0200 Subject: [PATCH 5/8] Change: Display IP info notification 20 seconds --- Web-UI/assets/css/style.css | 2 +- Web-UI/assets/js/action-collector.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Web-UI/assets/css/style.css b/Web-UI/assets/css/style.css index 82e22e1..52282d7 100644 --- a/Web-UI/assets/css/style.css +++ b/Web-UI/assets/css/style.css @@ -166,7 +166,7 @@ tr:nth-child(even) { font-family: monospace; font-size: 14px; opacity: 0.95; - animation: fadein 0.3s ease-out, fadeout 0.5s ease-in 4s forwards; + animation: fadein 0.3s ease-out, fadeout 0.5s ease-in 20s forwards; } @keyframes fadein { diff --git a/Web-UI/assets/js/action-collector.js b/Web-UI/assets/js/action-collector.js index ad74975..f2218d6 100644 --- a/Web-UI/assets/js/action-collector.js +++ b/Web-UI/assets/js/action-collector.js @@ -35,7 +35,7 @@ function collectAndExecuteActions(ips, action, jails = []) { const prefix = `[${action.toUpperCase()}] `; const message = data.message || 'No message returned.'; const type = data.type || (data.success ? 'success' : 'error'); - const duration = (action === 'report') ? 7000 : 7000; + const duration = (action === 'report') ? 25000 : 7000; showNotification(prefix + message, type, duration); }) .catch(err => { From bc5ae02bbf92453d0fc0c2ce3eb855ae94e37f79 Mon Sep 17 00:00:00 2001 From: Aleksandar Urosevic Date: Mon, 1 Sep 2025 16:50:18 +0200 Subject: [PATCH 6/8] Change: Hide login form when user is logged in --- Web-UI/includes/header.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Web-UI/includes/header.php b/Web-UI/includes/header.php index 3aa8b69..5e4814c 100644 --- a/Web-UI/includes/header.php +++ b/Web-UI/includes/header.php @@ -64,7 +64,7 @@ - +
@@ -76,12 +76,13 @@
+
- + From e016fb98193438a4182535d2b63de91b31ace522 Mon Sep 17 00:00:00 2001 From: Aleksandar Urosevic Date: Mon, 1 Sep 2025 16:50:50 +0200 Subject: [PATCH 7/8] Fix: location of favicon --- Web-UI/includes/header.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Web-UI/includes/header.php b/Web-UI/includes/header.php index 5e4814c..a37d60e 100644 --- a/Web-UI/includes/header.php +++ b/Web-UI/includes/header.php @@ -8,7 +8,7 @@ Fail2Ban Report - + From 20bf47177adf73266125d5fc153670b47e9a4464 Mon Sep 17 00:00:00 2001 From: Aleksandar Urosevic Date: Thu, 11 Sep 2025 09:25:55 +0200 Subject: [PATCH 8/8] Add support for IPv6 to log2json parser --- Backend/fail2ban_log2json.sh | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/Backend/fail2ban_log2json.sh b/Backend/fail2ban_log2json.sh index 6887ed8..dd6deff 100644 --- a/Backend/fail2ban_log2json.sh +++ b/Backend/fail2ban_log2json.sh @@ -1,5 +1,6 @@ #!/bin/bash -# This is the Logfile-Reader for the local installation - so you will have to edit the OUTPUT_JSON_DIR to fit your Webserver Installation +# This is the Logfile-Reader for the local installation +# You have to edit the OUTPUT_JSON_DIR to fit your Webserver Installation # LOGFILE="/var/log/fail2ban.log" OUTPUT_JSON_DIR="/var/www/html/Fail2Ban-Report/archive//fail2ban" @@ -9,27 +10,35 @@ TODAY=$(date +"%Y-%m-%d") OUTPUT_JSON_FILE="$OUTPUT_JSON_DIR/fail2ban-events-$(date +"%Y%m%d").json" mkdir -p "$OUTPUT_JSON_DIR" +# IPv4 regex: nnn.nnn.nnn.nnn (0-255 simplified to 0-999 for awk) +IPv4='([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})' +# IPv6 regex: blocks of hex split by collon, allowed "::" short format +IPv6='(([0-9A-Fa-f]{1,4}:){1,7}[0-9A-Fa-f]{1,4}|([0-9A-Fa-f]{1,4}:){1,7}:|:([0-9A-Fa-f]{1,4}:){1,7}[0-9A-Fa-f]{1,4}|::)' +# complete IPv4 and IPv6 pattern +IP_PATTERN="($IPv4|$IPv6)" + echo "[" > "$OUTPUT_JSON_FILE" # Grep all relevant Events -grep -E "(Ban|Unban)" "$LOGFILE" | awk -v today="$TODAY" ' +grep -E "(Ban|Unban)" "$LOGFILE" | awk -v today="$TODAY" -v ip_pattern="$IP_PATTERN" ' { timestamp = $1 " " $2; if (index(timestamp, today) != 1) next; action = ""; ip = ""; + if ($0 ~ /Increase Ban/) { action = "Increase Ban"; - match($0, /Increase Ban ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/, m); + match($0, action " " ip_pattern, m); if (m[1]) ip = m[1]; } else if ($0 ~ /Ban/) { action = "Ban"; - match($0, /Ban ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/, m); + match($0, action " " ip_pattern, m); if (m[1]) ip = m[1]; } else if ($0 ~ /Unban/) { action = "Unban"; - match($0, /Unban ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/, m); + match($0, action " " ip_pattern, m); if (m[1]) ip = m[1]; }