From 5163e4f1f4640728f7de656739177066e48df84b Mon Sep 17 00:00:00 2001 From: Michael Reber Date: Mon, 15 Dec 2025 18:57:50 +0100 Subject: [PATCH] Make default jail state configurable --- cmd/server/main.go | 5 ++--- docker-compose-allinone.example.yml | 2 +- internal/config/settings.go | 8 +++++++- internal/fail2ban/connector_agent.go | 1 + internal/fail2ban/connector_ssh.go | 29 +++++++++++++++++++--------- internal/fail2ban/jail_management.go | 7 ++++--- internal/locales/de.json | 2 ++ internal/locales/de_ch.json | 2 ++ internal/locales/en.json | 2 ++ internal/locales/es.json | 2 ++ internal/locales/fr.json | 2 ++ internal/locales/it.json | 2 ++ internal/storage/storage.go | 17 ++++++++++------ pkg/web/handlers.go | 2 ++ pkg/web/static/js/settings.js | 2 ++ pkg/web/templates/index.html | 9 +++++++++ 16 files changed, 71 insertions(+), 23 deletions(-) diff --git a/cmd/server/main.go b/cmd/server/main.go index 7d8bc20..e70b934 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -93,7 +93,6 @@ func main() { } } -// isLOTRModeActive checks if LOTR mode is enabled in alert countries func isLOTRModeActive(alertCountries []string) bool { if len(alertCountries) == 0 { return false @@ -106,10 +105,10 @@ func isLOTRModeActive(alertCountries []string) bool { return false } -// printWelcomeBanner prints a cool Tux banner with startup info. +// printWelcomeBanner prints the Tux banner with startup info. func printWelcomeBanner(appPort string, isLOTRMode bool) { greeting := getGreeting() - + if isLOTRMode { const lotrBanner = ` .--. diff --git a/docker-compose-allinone.example.yml b/docker-compose-allinone.example.yml index 6b362ad..dcc3081 100644 --- a/docker-compose-allinone.example.yml +++ b/docker-compose-allinone.example.yml @@ -29,7 +29,7 @@ services: image: registry.swissmakers.ch/infra/fail2ban-ui:latest #image: localhost/fail2ban-ui:dev container_name: fail2ban-ui - #privileged: true + privileged: true # needed because the fail2ban-ui container needs to modify the fail2ban config owned by root inside the linuxserver-fail2ban container network_mode: host environment: - PORT=3080 diff --git a/internal/config/settings.go b/internal/config/settings.go index 84e9f94..41764ac 100644 --- a/internal/config/settings.go +++ b/internal/config/settings.go @@ -61,6 +61,7 @@ type AppSettings struct { // Fail2Ban [DEFAULT] section values from jail.local BantimeIncrement bool `json:"bantimeIncrement"` + DefaultJailEnable bool `json:"defaultJailEnable"` IgnoreIPs []string `json:"ignoreips"` // Changed from string to []string for individual IP management Bantime string `json:"bantime"` Findtime string `json:"findtime"` @@ -351,6 +352,7 @@ func applyAppSettingsRecordLocked(rec storage.AppSettingsRecord) { currentSettings.CallbackURL = rec.CallbackURL currentSettings.RestartNeeded = rec.RestartNeeded currentSettings.BantimeIncrement = rec.BantimeIncrement + currentSettings.DefaultJailEnable = rec.DefaultJailEnable // Convert IgnoreIP string to array (backward compatibility) if rec.IgnoreIP != "" { currentSettings.IgnoreIPs = strings.Fields(rec.IgnoreIP) @@ -446,6 +448,7 @@ func toAppSettingsRecordLocked() (storage.AppSettingsRecord, error) { SMTPFrom: currentSettings.SMTP.From, SMTPUseTLS: currentSettings.SMTP.UseTLS, BantimeIncrement: currentSettings.BantimeIncrement, + DefaultJailEnable: currentSettings.DefaultJailEnable, // Convert IgnoreIPs array to space-separated string for storage IgnoreIP: strings.Join(currentSettings.IgnoreIPs, " "), Bantime: currentSettings.Bantime, @@ -808,6 +811,7 @@ func ensureJailLocalStructure() error { banactionAllports = "iptables-allports" } defaultSection := fmt.Sprintf(`[DEFAULT] +enabled = %t bantime.increment = %t ignoreip = %s bantime = %s @@ -817,7 +821,7 @@ destemail = %s banaction = %s banaction_allports = %s -`, settings.BantimeIncrement, ignoreIPStr, settings.Bantime, settings.Findtime, settings.Maxretry, settings.Destemail, banaction, banactionAllports) +`, settings.DefaultJailEnable, settings.BantimeIncrement, ignoreIPStr, settings.Bantime, settings.Findtime, settings.Maxretry, settings.Destemail, banaction, banactionAllports) // Build action_mwlg configuration // Note: action_mwlg depends on action_ which depends on banaction (now defined above) @@ -876,6 +880,7 @@ func updateJailLocalDefaultSection(settings AppSettings) error { } // Keys to update keysToUpdate := map[string]string{ + "enabled": fmt.Sprintf("enabled = %t", settings.DefaultJailEnable), "bantime.increment": fmt.Sprintf("bantime.increment = %t", settings.BantimeIncrement), "ignoreip": fmt.Sprintf("ignoreip = %s", ignoreIPStr), "bantime": fmt.Sprintf("bantime = %s", settings.Bantime), @@ -1347,6 +1352,7 @@ func UpdateSettings(new AppSettings) (AppSettings, error) { } } restartTriggered := old.BantimeIncrement != new.BantimeIncrement || + old.DefaultJailEnable != new.DefaultJailEnable || ignoreIPsChanged || old.Bantime != new.Bantime || old.Findtime != new.Findtime || diff --git a/internal/fail2ban/connector_agent.go b/internal/fail2ban/connector_agent.go index be7e8f1..1613471 100644 --- a/internal/fail2ban/connector_agent.go +++ b/internal/fail2ban/connector_agent.go @@ -386,6 +386,7 @@ func (ac *AgentConnector) UpdateDefaultSettings(ctx context.Context, settings co } payload := map[string]interface{}{ "bantimeIncrement": settings.BantimeIncrement, + "defaultJailEnable": settings.DefaultJailEnable, "ignoreip": ignoreIPStr, "bantime": settings.Bantime, "findtime": settings.Findtime, diff --git a/internal/fail2ban/connector_ssh.go b/internal/fail2ban/connector_ssh.go index d3ec1a2..d5d9866 100644 --- a/internal/fail2ban/connector_ssh.go +++ b/internal/fail2ban/connector_ssh.go @@ -952,6 +952,7 @@ func (sc *SSHConnector) UpdateDefaultSettings(ctx context.Context, settings conf } // Define the keys we want to update keysToUpdate := map[string]string{ + "enabled": fmt.Sprintf("enabled = %t", settings.DefaultJailEnable), "bantime.increment": fmt.Sprintf("bantime.increment = %t", settings.BantimeIncrement), "ignoreip": fmt.Sprintf("ignoreip = %s", ignoreIPStr), "bantime": fmt.Sprintf("bantime = %s", settings.Bantime), @@ -966,7 +967,7 @@ func (sc *SSHConnector) UpdateDefaultSettings(ctx context.Context, settings conf if existingContent == "" { // File doesn't exist, create new one with DEFAULT section defaultLines := []string{"[DEFAULT]"} - for _, key := range []string{"bantime.increment", "ignoreip", "bantime", "findtime", "maxretry", "destemail", "banaction", "banaction_allports"} { + for _, key := range []string{"enabled", "bantime.increment", "ignoreip", "bantime", "findtime", "maxretry", "destemail", "banaction", "banaction_allports"} { defaultLines = append(defaultLines, keysToUpdate[key]) } defaultLines = append(defaultLines, "") @@ -991,14 +992,20 @@ jail_file = '%s' ignore_ip_str = '%s' banaction_val = '%s' banaction_allports_val = '%s' +default_jail_enable_val = %t bantime_increment_val = %t +bantime_val = '%s' +findtime_val = '%s' +maxretry_val = %d +destemail_val = '%s' keys_to_update = { + 'enabled': 'enabled = ' + str(default_jail_enable_val), 'bantime.increment': 'bantime.increment = ' + str(bantime_increment_val), 'ignoreip': 'ignoreip = ' + ignore_ip_str, - 'bantime': 'bantime = %s', - 'findtime': 'findtime = %s', - 'maxretry': 'maxretry = %d', - 'destemail': 'destemail = %s', + 'bantime': 'bantime = ' + bantime_val, + 'findtime': 'findtime = ' + findtime_val, + 'maxretry': 'maxretry = ' + str(maxretry_val), + 'destemail': 'destemail = ' + destemail_val, 'banaction': 'banaction = ' + banaction_val, 'banaction_allports': 'banaction_allports = ' + banaction_allports_val } @@ -1051,13 +1058,13 @@ for line in lines: # If DEFAULT section wasn't found, create it at the beginning if not default_section_found: default_lines = ["[DEFAULT]\n"] - for key in ["bantime.increment", "ignoreip", "bantime", "findtime", "maxretry", "destemail"]: + for key in ["enabled", "bantime.increment", "ignoreip", "bantime", "findtime", "maxretry", "destemail"]: default_lines.append(keys_to_update[key] + "\n") default_lines.append("\n") output_lines = default_lines + output_lines else: # Add any missing keys to the DEFAULT section - for key in ["bantime.increment", "ignoreip", "bantime", "findtime", "maxretry", "destemail"]: + for key in ["enabled", "bantime.increment", "ignoreip", "bantime", "findtime", "maxretry", "destemail"]: if key not in keys_updated: # Find the DEFAULT section and insert after it for i, line in enumerate(output_lines): @@ -1067,7 +1074,7 @@ else: with open(jail_file, 'w') as f: f.writelines(output_lines) -PY`, escapeForShell(jailLocalPath), escapeForShell(ignoreIPStr), escapeForShell(banactionVal), escapeForShell(banactionAllportsVal), settings.BantimeIncrement, escapeForShell(settings.Bantime), escapeForShell(settings.Findtime), settings.Maxretry, escapeForShell(settings.Destemail)) +PY`, escapeForShell(jailLocalPath), escapeForShell(ignoreIPStr), escapeForShell(banactionVal), escapeForShell(banactionAllportsVal), settings.BantimeIncrement, settings.DefaultJailEnable, escapeForShell(settings.Bantime), escapeForShell(settings.Findtime), settings.Maxretry, escapeForShell(settings.Destemail)) _, err = sc.runRemoteCommand(ctx, []string{"bash", "-lc", updateScript}) return err @@ -1109,6 +1116,7 @@ banaction_allports_val = '%s' banner_content = """%s""" settings = { 'bantime_increment': %t, + 'default_jail_enable': %t, 'ignoreip': ignore_ip_str, 'bantime': '%s', 'findtime': '%s', @@ -1169,6 +1177,7 @@ if has_full_banner and has_action_mwlg and has_action_override: elif in_default: key_updated = False for key, new_value in [ + ('enabled', 'enabled = ' + str(settings['default_jail_enable'])), ('bantime.increment', 'bantime.increment = ' + str(settings['bantime_increment'])), ('ignoreip', 'ignoreip = ' + settings['ignoreip']), ('bantime', 'bantime = ' + settings['bantime']), @@ -1192,6 +1201,7 @@ if has_full_banner and has_action_mwlg and has_action_override: # Add missing keys if in_default: for key, new_value in [ + ('enabled', 'enabled = ' + str(settings['default_jail_enable'])), ('bantime.increment', 'bantime.increment = ' + str(settings['bantime_increment'])), ('ignoreip', 'ignoreip = ' + settings['ignoreip']), ('bantime', 'bantime = ' + settings['bantime']), @@ -1214,6 +1224,7 @@ else: banner = banner_content default_section = """[DEFAULT] +enabled = """ + str(settings['default_jail_enable']) + """ bantime.increment = """ + str(settings['bantime_increment']) + """ ignoreip = """ + settings['ignoreip'] + """ bantime = """ + settings['bantime'] + """ @@ -1239,7 +1250,7 @@ action = %%(action_mwlg)s with open(jail_file, 'w') as f: f.write(new_content) -PY`, escapeForShell(jailLocalPath), escapeForShell(ignoreIPStr), escapeForShell(banactionVal), escapeForShell(banactionAllportsVal), escapeForShell(config.JailLocalBanner()), settings.BantimeIncrement, +PY`, escapeForShell(jailLocalPath), escapeForShell(ignoreIPStr), escapeForShell(banactionVal), escapeForShell(banactionAllportsVal), escapeForShell(config.JailLocalBanner()), settings.BantimeIncrement, settings.DefaultJailEnable, escapeForShell(settings.Bantime), escapeForShell(settings.Findtime), settings.Maxretry, escapeForShell(settings.Destemail)) // IMPORTANT: Run migration FIRST before ensuring structure diff --git a/internal/fail2ban/jail_management.go b/internal/fail2ban/jail_management.go index ae14edd..7efe22d 100644 --- a/internal/fail2ban/jail_management.go +++ b/internal/fail2ban/jail_management.go @@ -1023,6 +1023,7 @@ func UpdateDefaultSettingsLocal(settings config.AppSettings) error { } // Define the keys we want to update keysToUpdate := map[string]string{ + "enabled": fmt.Sprintf("enabled = %t", settings.DefaultJailEnable), "bantime.increment": fmt.Sprintf("bantime.increment = %t", settings.BantimeIncrement), "ignoreip": fmt.Sprintf("ignoreip = %s", ignoreIPStr), "bantime": fmt.Sprintf("bantime = %s", settings.Bantime), @@ -1042,7 +1043,7 @@ func UpdateDefaultSettingsLocal(settings config.AppSettings) error { var newLines []string newLines = append(newLines, strings.Split(strings.TrimRight(config.JailLocalBanner(), "\n"), "\n")...) newLines = append(newLines, "[DEFAULT]") - for _, key := range []string{"bantime.increment", "ignoreip", "bantime", "findtime", "maxretry", "destemail", "banaction", "banaction_allports"} { + for _, key := range []string{"enabled", "bantime.increment", "ignoreip", "bantime", "findtime", "maxretry", "destemail", "banaction", "banaction_allports"} { newLines = append(newLines, keysToUpdate[key]) } newLines = append(newLines, "") @@ -1115,14 +1116,14 @@ func UpdateDefaultSettingsLocal(settings config.AppSettings) error { // If DEFAULT section wasn't found, create it at the beginning if !defaultSectionFound { defaultLines := []string{"[DEFAULT]"} - for _, key := range []string{"bantime.increment", "ignoreip", "bantime", "findtime", "maxretry", "destemail"} { + for _, key := range []string{"enabled", "bantime.increment", "ignoreip", "bantime", "findtime", "maxretry", "destemail"} { defaultLines = append(defaultLines, keysToUpdate[key]) } defaultLines = append(defaultLines, "") outputLines = append(defaultLines, outputLines...) } else { // Add any missing keys to the DEFAULT section - for _, key := range []string{"bantime.increment", "ignoreip", "bantime", "findtime", "maxretry", "destemail", "banaction", "banaction_allports"} { + for _, key := range []string{"enabled", "bantime.increment", "ignoreip", "bantime", "findtime", "maxretry", "destemail", "banaction", "banaction_allports"} { if !keysUpdated[key] { // Find the DEFAULT section and insert after it for i, line := range outputLines { diff --git a/internal/locales/de.json b/internal/locales/de.json index 55facb0..22eda74 100644 --- a/internal/locales/de.json +++ b/internal/locales/de.json @@ -123,6 +123,8 @@ "settings.fail2ban.description": "Diese Einstellungen werden auf allen aktivierten Fail2Ban-Servern angewendet und in deren jail.local [DEFAULT]-Abschnitt gespeichert.", "settings.enable_bantime_increment": "Bantime-Inkrement aktivieren", "settings.enable_bantime_increment.description": "Wenn auf true gesetzt, wird die Bantime nach der Formel: bantime = findtime * (Anzahl der Fehler / maxretry) * (1 + bantime.rndtime) berechnet.", + "settings.default_jail_enable": "Jails standardmässig aktivieren", + "settings.default_jail_enable.description": "Wenn aktiviert, werden alle Jails standardmässig aktiviert. Wenn deaktiviert, müssen Jails explizit aktiviert werden.", "settings.default_bantime": "Standard-Bantime", "settings.default_bantime.description": "Die Anzahl der Sekunden, für die ein Host gesperrt wird. Zeitformat: 1h = 1 Stunde, 1d = 1 Tag, 1w = 1 Woche, 1m = 1 Monat, 1y = 1 Jahr.", "settings.default_bantime_placeholder": "z.B. 48h", diff --git a/internal/locales/de_ch.json b/internal/locales/de_ch.json index 2006030..e11dd15 100644 --- a/internal/locales/de_ch.json +++ b/internal/locales/de_ch.json @@ -123,6 +123,8 @@ "settings.fail2ban.description": "Die Einstellige werde uf alli aktivierte Fail2Ban-Server aagwändet und i däre jail.local [DEFAULT]-Abschnitt gspeicheret.", "settings.enable_bantime_increment": "Bantime-Inkrement aktivierä", "settings.enable_bantime_increment.description": "Wenn uf true gsetzt, wird d Bantime nach dr Formle: bantime = findtime * (Aazahl vo de Fähler / maxretry) * (1 + bantime.rndtime) berechnet.", + "settings.default_jail_enable": "Jails standardmässig aktivieren", + "settings.default_jail_enable.description": "Wenn aktiviert, werde alli Jails standardmässig aktiviert. Wenn deaktiviert, mues jedes Jails explizit aktiviert werde.", "settings.default_bantime": "Standard-Bantime", "settings.default_bantime.description": "D Aazahl vo de Sekunde, wo ä Host gsperrt wird. Zytformat: 1h = 1 Stund, 1d = 1 Tag, 1w = 1 Wuche, 1m = 1 Monet, 1y = 1 Jahr.", "settings.default_bantime_placeholder": "z.B. 48h", diff --git a/internal/locales/en.json b/internal/locales/en.json index 5fb65f6..a81104c 100644 --- a/internal/locales/en.json +++ b/internal/locales/en.json @@ -123,6 +123,8 @@ "settings.fail2ban.description": "These settings will be applied to all enabled Fail2Ban servers and stored in their jail.local [DEFAULT] section.", "settings.enable_bantime_increment": "Enable Bantime Increment", "settings.enable_bantime_increment.description": "If set to true, the bantime will be calculated using the formula: bantime = findtime * (number of failures / maxretry) * (1 + bantime.rndtime).", + "settings.default_jail_enable": "Enable Jails by Default", + "settings.default_jail_enable.description": "If enabled, all jails will be enabled by default. When disabled, jails must be explicitly enabled.", "settings.default_bantime": "Default Bantime", "settings.default_bantime.description": "The number of seconds that a host is banned. Time format: 1h = 1 hour, 1d = 1 day, 1w = 1 week, 1m = 1 month, 1y = 1 year.", "settings.default_bantime_placeholder": "e.g., 48h", diff --git a/internal/locales/es.json b/internal/locales/es.json index 436ee8c..3005432 100644 --- a/internal/locales/es.json +++ b/internal/locales/es.json @@ -123,6 +123,8 @@ "settings.fail2ban.description": "Estas configuraciones se aplicarán a todos los servidores Fail2Ban habilitados y se almacenarán en su sección [DEFAULT] de jail.local.", "settings.enable_bantime_increment": "Habilitar incremento de Bantime", "settings.enable_bantime_increment.description": "Si se establece en true, el bantime se calculará usando la fórmula: bantime = findtime * (número de fallos / maxretry) * (1 + bantime.rndtime).", + "settings.default_jail_enable": "Jails por defecto activados", + "settings.default_jail_enable.description": "Si está habilitado, todos los jails estarán habilitados por defecto. Cuando está deshabilitado, los jails deben habilitarse explícitamente.", "settings.default_bantime": "Bantime por defecto", "settings.default_bantime.description": "El número de segundos que un host está bloqueado. Formato de tiempo: 1h = 1 hora, 1d = 1 día, 1w = 1 semana, 1m = 1 mes, 1y = 1 año.", "settings.default_bantime_placeholder": "p.ej., 48h", diff --git a/internal/locales/fr.json b/internal/locales/fr.json index b9d747e..dcdede8 100644 --- a/internal/locales/fr.json +++ b/internal/locales/fr.json @@ -123,6 +123,8 @@ "settings.fail2ban.description": "Ces paramètres seront appliqués à tous les serveurs Fail2Ban activés et stockés dans leur section [DEFAULT] de jail.local.", "settings.enable_bantime_increment": "Activer l'incrémentation du Bantime", "settings.enable_bantime_increment.description": "Si défini sur true, le bantime sera calculé à l'aide de la formule : bantime = findtime * (nombre d'échecs / maxretry) * (1 + bantime.rndtime).", + "settings.default_jail_enable": "Jails par défaut activés", + "settings.default_jail_enable.description": "Si activé, tous les jails seront activés par défaut. Lorsqu'il est désactivé, les jails doivent être explicitement activés.", "settings.default_bantime": "Bantime par défaut", "settings.default_bantime.description": "Le nombre de secondes pendant lesquelles un hôte est banni. Format de temps : 1h = 1 heure, 1d = 1 jour, 1w = 1 semaine, 1m = 1 mois, 1y = 1 an.", "settings.default_bantime_placeholder": "par exemple, 48h", diff --git a/internal/locales/it.json b/internal/locales/it.json index 15b0ce4..7ed02db 100644 --- a/internal/locales/it.json +++ b/internal/locales/it.json @@ -123,6 +123,8 @@ "settings.fail2ban.description": "Queste impostazioni verranno applicate a tutti i server Fail2Ban abilitati e memorizzate nella loro sezione [DEFAULT] di jail.local.", "settings.enable_bantime_increment": "Abilita incremento del Bantime", "settings.enable_bantime_increment.description": "Se impostato su true, il bantime verrà calcolato utilizzando la formula: bantime = findtime * (numero di errori / maxretry) * (1 + bantime.rndtime).", + "settings.default_jail_enable": "Jails predefiniti attivati", + "settings.default_jail_enable.description": "Se abilitato, tutti i jails saranno abilitati per impostazione predefinita. Quando disabilitato, i jails devono essere esplicitamente abilitati.", "settings.default_bantime": "Bantime predefinito", "settings.default_bantime.description": "Il numero di secondi per cui un host viene bannato. Formato tempo: 1h = 1 ora, 1d = 1 giorno, 1w = 1 settimana, 1m = 1 mese, 1y = 1 anno.", "settings.default_bantime_placeholder": "es. 48h", diff --git a/internal/storage/storage.go b/internal/storage/storage.go index a3647c1..5de48a6 100644 --- a/internal/storage/storage.go +++ b/internal/storage/storage.go @@ -61,6 +61,7 @@ type AppSettingsRecord struct { SMTPFrom string SMTPUseTLS bool BantimeIncrement bool + DefaultJailEnable bool IgnoreIP string // Stored as space-separated string, converted to array in AppSettings Bantime string Findtime string @@ -170,17 +171,17 @@ func GetAppSettings(ctx context.Context) (AppSettingsRecord, bool, error) { } row := db.QueryRowContext(ctx, ` -SELECT language, port, debug, callback_url, restart_needed, alert_countries, smtp_host, smtp_port, smtp_username, smtp_password, smtp_from, smtp_use_tls, bantime_increment, ignore_ip, bantime, findtime, maxretry, destemail, banaction, banaction_allports, advanced_actions +SELECT language, port, debug, callback_url, restart_needed, alert_countries, smtp_host, smtp_port, smtp_username, smtp_password, smtp_from, smtp_use_tls, bantime_increment, default_jail_enable, ignore_ip, bantime, findtime, maxretry, destemail, banaction, banaction_allports, advanced_actions FROM app_settings WHERE id = 1`) var ( lang, callback, alerts, smtpHost, smtpUser, smtpPass, smtpFrom, ignoreIP, bantime, findtime, destemail, banaction, banactionAllports, advancedActions sql.NullString - port, smtpPort, maxretry sql.NullInt64 - debug, restartNeeded, smtpTLS, bantimeInc sql.NullInt64 + port, smtpPort, maxretry sql.NullInt64 + debug, restartNeeded, smtpTLS, bantimeInc, defaultJailEn sql.NullInt64 ) - err := row.Scan(&lang, &port, &debug, &callback, &restartNeeded, &alerts, &smtpHost, &smtpPort, &smtpUser, &smtpPass, &smtpFrom, &smtpTLS, &bantimeInc, &ignoreIP, &bantime, &findtime, &maxretry, &destemail, &banaction, &banactionAllports, &advancedActions) + err := row.Scan(&lang, &port, &debug, &callback, &restartNeeded, &alerts, &smtpHost, &smtpPort, &smtpUser, &smtpPass, &smtpFrom, &smtpTLS, &bantimeInc, &defaultJailEn, &ignoreIP, &bantime, &findtime, &maxretry, &destemail, &banaction, &banactionAllports, &advancedActions) if errors.Is(err, sql.ErrNoRows) { return AppSettingsRecord{}, false, nil } @@ -202,6 +203,7 @@ WHERE id = 1`) SMTPFrom: stringFromNull(smtpFrom), SMTPUseTLS: intToBool(intFromNull(smtpTLS)), BantimeIncrement: intToBool(intFromNull(bantimeInc)), + DefaultJailEnable: intToBool(intFromNull(defaultJailEn)), IgnoreIP: stringFromNull(ignoreIP), Bantime: stringFromNull(bantime), Findtime: stringFromNull(findtime), @@ -221,9 +223,9 @@ func SaveAppSettings(ctx context.Context, rec AppSettingsRecord) error { } _, err := db.ExecContext(ctx, ` INSERT INTO app_settings ( - id, language, port, debug, callback_url, restart_needed, alert_countries, smtp_host, smtp_port, smtp_username, smtp_password, smtp_from, smtp_use_tls, bantime_increment, ignore_ip, bantime, findtime, maxretry, destemail, banaction, banaction_allports, advanced_actions + id, language, port, debug, callback_url, restart_needed, alert_countries, smtp_host, smtp_port, smtp_username, smtp_password, smtp_from, smtp_use_tls, bantime_increment, default_jail_enable, ignore_ip, bantime, findtime, maxretry, destemail, banaction, banaction_allports, advanced_actions ) VALUES ( - 1, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? + 1, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ) ON CONFLICT(id) DO UPDATE SET language = excluded.language, port = excluded.port, @@ -238,6 +240,7 @@ INSERT INTO app_settings ( smtp_from = excluded.smtp_from, smtp_use_tls = excluded.smtp_use_tls, bantime_increment = excluded.bantime_increment, + default_jail_enable = excluded.default_jail_enable, ignore_ip = excluded.ignore_ip, bantime = excluded.bantime, findtime = excluded.findtime, @@ -259,6 +262,7 @@ INSERT INTO app_settings ( rec.SMTPFrom, boolToInt(rec.SMTPUseTLS), boolToInt(rec.BantimeIncrement), + boolToInt(rec.DefaultJailEnable), rec.IgnoreIP, rec.Bantime, rec.Findtime, @@ -775,6 +779,7 @@ CREATE TABLE IF NOT EXISTS app_settings ( smtp_from TEXT, smtp_use_tls INTEGER, bantime_increment INTEGER, + default_jail_enable INTEGER, ignore_ip TEXT, bantime TEXT, findtime TEXT, diff --git a/pkg/web/handlers.go b/pkg/web/handlers.go index b6db0a6..b72299d 100644 --- a/pkg/web/handlers.go +++ b/pkg/web/handlers.go @@ -1333,6 +1333,7 @@ func UpdateSettingsHandler(c *gin.Context) { // Compare IgnoreIPs arrays ignoreIPsChanged := !equalStringSlices(oldSettings.IgnoreIPs, newSettings.IgnoreIPs) defaultSettingsChanged := oldSettings.BantimeIncrement != newSettings.BantimeIncrement || + oldSettings.DefaultJailEnable != newSettings.DefaultJailEnable || ignoreIPsChanged || oldSettings.Bantime != newSettings.Bantime || oldSettings.Findtime != newSettings.Findtime || @@ -1459,6 +1460,7 @@ func ApplyFail2banSettings(jailLocalPath string) error { newLines := []string{ "[DEFAULT]", + fmt.Sprintf("enabled = %t", s.DefaultJailEnable), fmt.Sprintf("bantime.increment = %t", s.BantimeIncrement), fmt.Sprintf("ignoreip = %s", strings.Join(s.IgnoreIPs, " ")), fmt.Sprintf("bantime = %s", s.Bantime), diff --git a/pkg/web/static/js/settings.js b/pkg/web/static/js/settings.js index 55fbcac..c16cff5 100644 --- a/pkg/web/static/js/settings.js +++ b/pkg/web/static/js/settings.js @@ -82,6 +82,7 @@ function loadSettings() { } document.getElementById('bantimeIncrement').checked = data.bantimeIncrement || false; + document.getElementById('defaultJailEnable').checked = data.defaultJailEnable || false; document.getElementById('banTime').value = data.bantime || ''; document.getElementById('findTime').value = data.findtime || ''; document.getElementById('maxRetry').value = data.maxretry || ''; @@ -141,6 +142,7 @@ function saveSettings(event) { callbackUrl: callbackUrl, alertCountries: selectedCountries.length > 0 ? selectedCountries : ["ALL"], bantimeIncrement: document.getElementById('bantimeIncrement').checked, + defaultJailEnable: document.getElementById('defaultJailEnable').checked, bantime: document.getElementById('banTime').value.trim(), findtime: document.getElementById('findTime').value.trim(), maxretry: parseInt(document.getElementById('maxRetry').value, 10) || 3, diff --git a/pkg/web/templates/index.html b/pkg/web/templates/index.html index a4993d5..1fa5e22 100644 --- a/pkg/web/templates/index.html +++ b/pkg/web/templates/index.html @@ -585,6 +585,15 @@

If set to true, the bantime will be calculated using the formula: bantime = findtime * (number of failures / maxretry) * (1 + bantime.rndtime).

+ + +
+
+ + +
+

If enabled, all jails will be enabled by default. When disabled, jails must be explicitly enabled.

+