From 98440c456a98560187223e41f06f5e9f61f5159e Mon Sep 17 00:00:00 2001 From: CyberMind-FR Date: Mon, 2 Feb 2026 16:15:40 +0100 Subject: [PATCH] feat(ui): Add WAF auto-ban statistics to dashboards CrowdSec Dashboard: - Added WAF Threats and WAF Auto-Bans stats cards - Added WAF Auto-Ban status to health checks - Shows sensitivity level (aggressive/moderate/permissive) mitmproxy Status: - Added WAF Auto-Ban section with statistics - Shows threats today, bans today, total bans - Displays sensitivity level with color coding - Shows pending bans count when applicable Co-Authored-By: Claude Opus 4.5 --- .../view/crowdsec-dashboard/overview.js | 10 ++-- .../usr/libexec/rpcd/luci.crowdsec-dashboard | 37 ++++++++++++++ .../resources/view/mitmproxy/status.js | 48 +++++++++++++++++++ .../root/usr/libexec/rpcd/luci.mitmproxy | 39 ++++++++++++++- 4 files changed, 129 insertions(+), 5 deletions(-) diff --git a/package/secubox/luci-app-crowdsec-dashboard/htdocs/luci-static/resources/view/crowdsec-dashboard/overview.js b/package/secubox/luci-app-crowdsec-dashboard/htdocs/luci-static/resources/view/crowdsec-dashboard/overview.js index 1a9575bd..5fbc191d 100644 --- a/package/secubox/luci-app-crowdsec-dashboard/htdocs/luci-static/resources/view/crowdsec-dashboard/overview.js +++ b/package/secubox/luci-app-crowdsec-dashboard/htdocs/luci-static/resources/view/crowdsec-dashboard/overview.js @@ -119,8 +119,8 @@ return view.extend({ var stats = [ { label: 'Active Bans', value: s.active_bans || 0, type: (s.active_bans || 0) > 0 ? 'success' : '' }, { label: 'Alerts (24h)', value: s.alerts_24h || 0, type: (s.alerts_24h || 0) > 10 ? 'warning' : '' }, - { label: 'Blocked Packets', value: this.fmt(s.dropped_packets || 0), type: (s.dropped_packets || 0) > 0 ? 'danger' : '' }, - { label: 'Bouncers', value: s.bouncer_count || 0, type: (s.bouncer_count || 0) > 0 ? 'success' : 'warning' } + { label: 'WAF Threats', value: s.waf_threats_today || 0, type: (s.waf_threats_today || 0) > 0 ? 'warning' : '' }, + { label: 'WAF Auto-Bans', value: s.waf_bans_today || 0, type: (s.waf_bans_today || 0) > 0 ? 'danger' : '' } ]; return stats.map(function(st) { return E('div', { 'class': 'cs-stat ' + st.type }, [ @@ -158,14 +158,16 @@ return view.extend({ { label: 'LAPI', ok: s.lapi_status === 'available' }, { label: 'CAPI', ok: s.capi_enrolled }, { label: 'Bouncer', ok: (s.bouncer_count || 0) > 0 }, - { label: 'GeoIP', ok: s.geoip_enabled } + { label: 'GeoIP', ok: s.geoip_enabled }, + { label: 'WAF Auto-Ban', ok: s.waf_autoban_enabled, value: s.waf_sensitivity } ]; return E('div', { 'class': 'cs-health' }, checks.map(function(c) { + var valueText = c.value ? c.value : (c.ok ? 'OK' : 'Disabled'); return E('div', { 'class': 'cs-health-item' }, [ E('div', { 'class': 'cs-health-icon ' + (c.ok ? 'ok' : 'error') }, c.ok ? '\u2713' : '\u2717'), E('div', {}, [ E('div', { 'class': 'cs-health-label' }, c.label), - E('div', { 'class': 'cs-health-value' }, c.ok ? 'OK' : 'Error') + E('div', { 'class': 'cs-health-value' }, valueText) ]) ]); })); diff --git a/package/secubox/luci-app-crowdsec-dashboard/root/usr/libexec/rpcd/luci.crowdsec-dashboard b/package/secubox/luci-app-crowdsec-dashboard/root/usr/libexec/rpcd/luci.crowdsec-dashboard index f8e97aeb..57107dcd 100755 --- a/package/secubox/luci-app-crowdsec-dashboard/root/usr/libexec/rpcd/luci.crowdsec-dashboard +++ b/package/secubox/luci-app-crowdsec-dashboard/root/usr/libexec/rpcd/luci.crowdsec-dashboard @@ -2373,6 +2373,43 @@ get_overview() { [ -f /etc/crowdsec/online_api_credentials.yaml ] && capi_enrolled=1 json_add_boolean "capi_enrolled" "$capi_enrolled" + # WAF Autoban statistics (from mitmproxy) + local waf_autoban_enabled=0 + local waf_bans_today=0 + local waf_threats_today=0 + local waf_sensitivity="" + + # Check if mitmproxy autoban is enabled + waf_autoban_enabled=$(uci -q get mitmproxy.autoban.enabled 2>/dev/null || echo 0) + waf_sensitivity=$(uci -q get mitmproxy.autoban.sensitivity 2>/dev/null || echo "moderate") + + # Count WAF-originated bans in CrowdSec (reason contains "mitmproxy-waf") + if [ "$cs_running" = "1" ] && [ -x "$CSCLI" ]; then + waf_bans_today=$(run_cscli decisions list -o json 2>/dev/null | \ + grep -c "mitmproxy-waf" 2>/dev/null || echo 0) + fi + + # Count threats from mitmproxy log today + local threats_log="/srv/mitmproxy/threats.log" + if [ -f "$threats_log" ]; then + local today + today=$(date -u +%Y-%m-%d) + waf_threats_today=$(grep -c "\"timestamp\": \"$today" "$threats_log" 2>/dev/null || echo 0) + fi + + # Count processed autobans + local autoban_processed=0 + local autoban_log="/srv/mitmproxy/autoban-processed.log" + if [ -f "$autoban_log" ]; then + autoban_processed=$(wc -l < "$autoban_log" 2>/dev/null || echo 0) + fi + + json_add_boolean "waf_autoban_enabled" "$waf_autoban_enabled" + json_add_string "waf_sensitivity" "$waf_sensitivity" + json_add_int "waf_bans_today" "${waf_bans_today:-0}" + json_add_int "waf_threats_today" "${waf_threats_today:-0}" + json_add_int "waf_autoban_total" "${autoban_processed:-0}" + json_dump } diff --git a/package/secubox/luci-app-mitmproxy/htdocs/luci-static/resources/view/mitmproxy/status.js b/package/secubox/luci-app-mitmproxy/htdocs/luci-static/resources/view/mitmproxy/status.js index a44c38be..b8b2c7bc 100644 --- a/package/secubox/luci-app-mitmproxy/htdocs/luci-static/resources/view/mitmproxy/status.js +++ b/package/secubox/luci-app-mitmproxy/htdocs/luci-static/resources/view/mitmproxy/status.js @@ -162,6 +162,54 @@ return view.extend({ ]) ]), + // Auto-Ban Statistics Card + E('div', { 'class': 'cbi-section' }, [ + E('h3', {}, _('WAF Auto-Ban')), + E('div', { 'class': 'cbi-section-node' }, [ + E('table', { 'class': 'table' }, [ + E('tr', { 'class': 'tr' }, [ + E('td', { 'class': 'td', 'width': '33%' }, E('strong', {}, _('Auto-Ban'))), + E('td', { 'class': 'td' }, [ + E('span', { + 'style': 'display: inline-block; width: 12px; height: 12px; border-radius: 50%; margin-right: 8px; background: ' + (status.autoban_enabled ? '#27ae60' : '#95a5a6') + }), + status.autoban_enabled ? _('Enabled') : _('Disabled') + ]) + ]), + E('tr', { 'class': 'tr' }, [ + E('td', { 'class': 'td' }, E('strong', {}, _('Sensitivity'))), + E('td', { 'class': 'td' }, [ + E('span', { + 'style': 'background: ' + ({ aggressive: '#e74c3c', moderate: '#f39c12', permissive: '#27ae60' }[status.autoban_sensitivity] || '#666') + '; color: white; padding: 2px 8px; border-radius: 4px; font-size: 11px; text-transform: uppercase;' + }, status.autoban_sensitivity || 'moderate') + ]) + ]), + E('tr', { 'class': 'tr' }, [ + E('td', { 'class': 'td' }, E('strong', {}, _('Ban Duration'))), + E('td', { 'class': 'td' }, status.autoban_duration || '4h') + ]) + ]), + E('div', { 'style': 'display: flex; gap: 24px; margin-top: 16px; padding: 12px; background: #f8f9fa; border-radius: 8px;' }, [ + E('div', { 'style': 'text-align: center; flex: 1;' }, [ + E('div', { 'style': 'font-size: 28px; font-weight: bold; color: #e67e22;' }, String(status.threats_today || 0)), + E('div', { 'style': 'font-size: 12px; color: #666;' }, _('Threats Today')) + ]), + E('div', { 'style': 'text-align: center; flex: 1;' }, [ + E('div', { 'style': 'font-size: 28px; font-weight: bold; color: #e74c3c;' }, String(status.autobans_today || 0)), + E('div', { 'style': 'font-size: 12px; color: #666;' }, _('Bans Today')) + ]), + E('div', { 'style': 'text-align: center; flex: 1;' }, [ + E('div', { 'style': 'font-size: 28px; font-weight: bold; color: #3498db;' }, String(status.autobans_total || 0)), + E('div', { 'style': 'font-size: 12px; color: #666;' }, _('Total Bans')) + ]), + status.autobans_pending > 0 ? E('div', { 'style': 'text-align: center; flex: 1;' }, [ + E('div', { 'style': 'font-size: 28px; font-weight: bold; color: #9b59b6;' }, String(status.autobans_pending)), + E('div', { 'style': 'font-size: 12px; color: #666;' }, _('Pending')) + ]) : null + ]) + ]) + ]), + // HAProxy Backend Inspection Card E('div', { 'class': 'cbi-section' }, [ E('h3', {}, _('HAProxy Backend Inspection')), diff --git a/package/secubox/luci-app-mitmproxy/root/usr/libexec/rpcd/luci.mitmproxy b/package/secubox/luci-app-mitmproxy/root/usr/libexec/rpcd/luci.mitmproxy index f92c7773..84548672 100755 --- a/package/secubox/luci-app-mitmproxy/root/usr/libexec/rpcd/luci.mitmproxy +++ b/package/secubox/luci-app-mitmproxy/root/usr/libexec/rpcd/luci.mitmproxy @@ -57,6 +57,36 @@ get_status() { local token_file="${data_path:-/srv/mitmproxy}/.mitmproxy_token" [ -f "$token_file" ] && token=$(cat "$token_file" 2>/dev/null | tr -d '\n') + # Auto-ban stats + local autoban_enabled=$(uci_get autoban.enabled) + local autoban_sensitivity=$(uci_get autoban.sensitivity) + local autoban_duration=$(uci_get autoban.ban_duration) + + # Count threats today + local threats_today=0 + local threats_log="${data_path:-/srv/mitmproxy}/threats.log" + if [ -f "$threats_log" ]; then + local today=$(date -u +%Y-%m-%d) + threats_today=$(grep -c "\"timestamp\": \"$today" "$threats_log" 2>/dev/null || echo 0) + fi + + # Count processed autobans + local autobans_total=0 + local autobans_today=0 + local autoban_log="${data_path:-/srv/mitmproxy}/autoban-processed.log" + if [ -f "$autoban_log" ]; then + autobans_total=$(wc -l < "$autoban_log" 2>/dev/null || echo 0) + local today=$(date +%Y-%m-%d) + autobans_today=$(grep -c "^$today" "$autoban_log" 2>/dev/null || echo 0) + fi + + # Pending autoban requests + local autobans_pending=0 + local autoban_requests="${data_path:-/srv/mitmproxy}/autoban-requests.log" + if [ -f "$autoban_requests" ] && [ -s "$autoban_requests" ]; then + autobans_pending=$(wc -l < "$autoban_requests" 2>/dev/null || echo 0) + fi + cat <