From 514c9dd44416447c9a9f7ee631925727b9237ce0 Mon Sep 17 00:00:00 2001 From: Michael Reber Date: Wed, 11 Feb 2026 17:23:38 +0100 Subject: [PATCH] Implementing auto-disable of the jail when reload fails after saving filter/jail config --- internal/locales/de.json | 1 + internal/locales/de_ch.json | 1 + internal/locales/en.json | 1 + internal/locales/es.json | 1 + internal/locales/fr.json | 1 + internal/locales/it.json | 1 + pkg/web/handlers.go | 19 +++++++++++++++++-- pkg/web/static/js/jails.js | 9 ++++++++- 8 files changed, 31 insertions(+), 3 deletions(-) diff --git a/internal/locales/de.json b/internal/locales/de.json index d575892..78f15e3 100644 --- a/internal/locales/de.json +++ b/internal/locales/de.json @@ -353,6 +353,7 @@ "filter_debug.local_missing": "Das lokale Fail2ban-Filterverzeichnis wurde auf diesem Host nicht gefunden.", "filter_debug.save_success": "Filter- und Jail-Konfiguration gespeichert und Fail2ban neu geladen", "filter_debug.save_reload_warning": "Konfiguration gespeichert, aber Fail2ban-Reload fehlgeschlagen", + "filter_debug.jail_auto_disabled": "Jail '%s' wurde automatisch deaktiviert.", "email.ban.title": "Achtung: Fail2Ban hat eine neue IP-Adresse blockiert", "email.ban.intro": "Fail2Ban-UI hat eine fehlerhafte Anfrage oder wiederholte Authentifizierungsfehler erkannt und die Quell-IP automatisch blockiert. Überprüfen Sie die Metadaten und Log-Auszüge unten.", "email.ban.subject.banned": "Gesperrt", diff --git a/internal/locales/de_ch.json b/internal/locales/de_ch.json index d269d26..574f677 100644 --- a/internal/locales/de_ch.json +++ b/internal/locales/de_ch.json @@ -353,6 +353,7 @@ "filter_debug.local_missing": "S lokale Fail2ban-Filterverzeichnis isch uf däm Host nid gfunde worde.", "filter_debug.save_success": "Filter- und Jail-Konfiguration gspicheret und Fail2ban neu glade", "filter_debug.save_reload_warning": "Konfiguration gspicheret, aber z'Reload isch fähugschlage", + "filter_debug.jail_auto_disabled": "Jail '%s' isch automatisch deaktiviert worde.", "email.ban.title": "Achtung: Fail2Ban het e nöi IP-Adrässe blockiert", "email.ban.intro": "Fail2Ban-UI het e fehlerhafti Aafrag oder widerholti Authentifizierigsfähler erkennt und d Quell-IP automatisch blockiert. Überprüef d Metadate und Log-Uuszüg unge.", "email.ban.subject.banned": "G'sperrt", diff --git a/internal/locales/en.json b/internal/locales/en.json index ac24958..bfbf768 100644 --- a/internal/locales/en.json +++ b/internal/locales/en.json @@ -353,6 +353,7 @@ "filter_debug.local_missing": "The local Fail2ban filter directory was not found on this host.", "filter_debug.save_success": "Filter and jail config saved and reloaded", "filter_debug.save_reload_warning": "Config saved, but fail2ban reload failed", + "filter_debug.jail_auto_disabled": "Jail '%s' was automatically disabled.", "email.ban.title": "Security alert: Fail2Ban blocked a new IP-address", "email.ban.intro": "Fail2Ban-UI detected a bad request or repeated authentication failures and automatically blocked the source-IP. Review the metadata and log excerpts below.", "email.ban.subject.banned": "Banned", diff --git a/internal/locales/es.json b/internal/locales/es.json index d85b6dd..5324cc8 100644 --- a/internal/locales/es.json +++ b/internal/locales/es.json @@ -353,6 +353,7 @@ "filter_debug.local_missing": "No se encontró el directorio de filtros local de Fail2ban en este host.", "filter_debug.save_success": "Configuración de filtro y jail guardada y Fail2ban recargado", "filter_debug.save_reload_warning": "Configuración guardada, pero la recarga de Fail2ban falló", + "filter_debug.jail_auto_disabled": "El jail '%s' se desactivó automáticamente.", "email.ban.title": "Alerta de seguridad: Fail2Ban bloqueó una nueva dirección IP", "email.ban.intro": "Fail2Ban-UI detectó una solicitud incorrecta o fallos de autenticación repetidos y bloqueó automáticamente la IP de origen. Revise los metadatos y extractos de registro a continuación.", "email.ban.subject.banned": "Bloqueado", diff --git a/internal/locales/fr.json b/internal/locales/fr.json index f5a8322..e8e22a0 100644 --- a/internal/locales/fr.json +++ b/internal/locales/fr.json @@ -353,6 +353,7 @@ "filter_debug.local_missing": "Le répertoire de filtres Fail2ban local est introuvable sur cet hôte.", "filter_debug.save_success": "Configuration de filtre et jail enregistrée et Fail2ban rechargé", "filter_debug.save_reload_warning": "Configuration enregistrée, mais le rechargement de Fail2ban a échoué", + "filter_debug.jail_auto_disabled": "Le jail '%s' a été désactivé automatiquement.", "email.ban.title": "Alerte de sécurité : Fail2Ban a bloqué une nouvelle adresse IP", "email.ban.intro": "Fail2Ban-UI a détecté une requête suspecte ou des échecs d'authentification répétés et a automatiquement bloqué l'IP source. Consultez les métadonnées et extraits de journaux ci-dessous.", "email.ban.subject.banned": "Bloqué", diff --git a/internal/locales/it.json b/internal/locales/it.json index 6a9e0ac..34a8805 100644 --- a/internal/locales/it.json +++ b/internal/locales/it.json @@ -353,6 +353,7 @@ "filter_debug.local_missing": "La directory dei filtri Fail2ban locale non è stata trovata su questo host.", "filter_debug.save_success": "Configurazione di filtro e jail salvata e Fail2ban ricaricato", "filter_debug.save_reload_warning": "Configurazione salvata, ma il ricaricamento di Fail2ban non è riuscito", + "filter_debug.jail_auto_disabled": "Il jail '%s' è stato disattivato automaticamente.", "email.ban.title": "Allerta di sicurezza: Fail2Ban ha bloccato un nuovo indirizzo IP", "email.ban.intro": "Fail2Ban-UI ha rilevato una richiesta sospetta o ripetuti fallimenti di autenticazione e ha automaticamente bloccato l'IP sorgente. Rivedere i metadati e gli estratti di log di seguito.", "email.ban.subject.banned": "Bloccato", diff --git a/pkg/web/handlers.go b/pkg/web/handlers.go index 995f7e6..b4fbc7b 100644 --- a/pkg/web/handlers.go +++ b/pkg/web/handlers.go @@ -1459,9 +1459,24 @@ func SetJailFilterConfigHandler(c *gin.Context) { config.DebugLog("Reloading fail2ban") if err := conn.Reload(c.Request.Context()); err != nil { log.Printf("⚠️ Config saved but fail2ban reload failed: %v", err) + // Auto-disable this jail so fail2ban won't crash on next restart (invalid filter/jail config) + disableUpdate := map[string]bool{jail: false} + if disableErr := conn.UpdateJailEnabledStates(c.Request.Context(), disableUpdate); disableErr != nil { + log.Printf("⚠️ Failed to auto-disable jail %s after reload failure: %v", jail, disableErr) + c.JSON(http.StatusOK, gin.H{ + "message": "Config saved successfully, but fail2ban reload failed", + "warning": err.Error(), + }) + return + } + if reloadErr2 := conn.Reload(c.Request.Context()); reloadErr2 != nil { + log.Printf("⚠️ Failed to reload fail2ban after auto-disabling jail %s: %v", jail, reloadErr2) + } c.JSON(http.StatusOK, gin.H{ - "message": "Config saved successfully, but fail2ban reload failed", - "warning": err.Error(), + "message": "Config saved successfully, but fail2ban reload failed", + "warning": err.Error(), + "jailAutoDisabled": true, + "jailName": jail, }) return } diff --git a/pkg/web/static/js/jails.js b/pkg/web/static/js/jails.js index f1580fa..1c3ce70 100644 --- a/pkg/web/static/js/jails.js +++ b/pkg/web/static/js/jails.js @@ -156,7 +156,14 @@ function saveJailConfig() { } closeModal('jailConfigModal'); if (data.warning) { - showToast(t('filter_debug.save_reload_warning', 'Config saved, but fail2ban reload failed') + ': ' + data.warning, 'warning', 12000); + var warnMsg = t('filter_debug.save_reload_warning', 'Config saved, but fail2ban reload failed') + ': ' + data.warning; + if (data.jailAutoDisabled && data.jailName) { + warnMsg = (typeof t === 'function' ? t('filter_debug.jail_auto_disabled', "Jail '%s' was automatically disabled.").replace('%s', data.jailName) : "Jail '" + data.jailName + "' was automatically disabled.") + ' ' + warnMsg; + var toggleId = 'toggle-' + data.jailName.replace(/[^a-zA-Z0-9]/g, '_'); + var cb = document.getElementById(toggleId); + if (cb) cb.checked = false; + } + showToast(warnMsg, 'warning', 12000); } else { showToast(t('filter_debug.save_success', 'Filter and jail config saved and reloaded'), 'success'); }