mirror of
https://github.com/swissmakers/fail2ban-ui.git
synced 2026-04-17 05:53:15 +02:00
rework the reload function. we must change that to restart, because fail2ban does not apply all changes on reload only
This commit is contained in:
@@ -43,7 +43,7 @@ type AppSettings struct {
|
|||||||
Language string `json:"language"`
|
Language string `json:"language"`
|
||||||
Port int `json:"port"`
|
Port int `json:"port"`
|
||||||
Debug bool `json:"debug"`
|
Debug bool `json:"debug"`
|
||||||
ReloadNeeded bool `json:"reloadNeeded"`
|
RestartNeeded bool `json:"restartNeeded"`
|
||||||
AlertCountries []string `json:"alertCountries"`
|
AlertCountries []string `json:"alertCountries"`
|
||||||
SMTP SMTPSettings `json:"smtp"`
|
SMTP SMTPSettings `json:"smtp"`
|
||||||
|
|
||||||
@@ -406,25 +406,25 @@ func GetSettings() AppSettings {
|
|||||||
return currentSettings
|
return currentSettings
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarkReloadNeeded sets reloadNeeded = true and saves JSON
|
// MarkRestartNeeded sets restartNeeded = true and saves JSON
|
||||||
func MarkReloadNeeded() error {
|
func MarkRestartNeeded() error {
|
||||||
settingsLock.Lock()
|
settingsLock.Lock()
|
||||||
defer settingsLock.Unlock()
|
defer settingsLock.Unlock()
|
||||||
|
|
||||||
currentSettings.ReloadNeeded = true
|
currentSettings.RestartNeeded = true
|
||||||
return saveSettings()
|
return saveSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarkReloadDone sets reloadNeeded = false and saves JSON
|
// MarkRestartDone sets restartNeeded = false and saves JSON
|
||||||
func MarkReloadDone() error {
|
func MarkRestartDone() error {
|
||||||
settingsLock.Lock()
|
settingsLock.Lock()
|
||||||
defer settingsLock.Unlock()
|
defer settingsLock.Unlock()
|
||||||
|
|
||||||
currentSettings.ReloadNeeded = false
|
currentSettings.RestartNeeded = false
|
||||||
return saveSettings()
|
return saveSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateSettings merges new settings with old and sets reloadNeeded if needed
|
// UpdateSettings merges new settings with old and sets restartNeeded if needed
|
||||||
func UpdateSettings(new AppSettings) (AppSettings, error) {
|
func UpdateSettings(new AppSettings) (AppSettings, error) {
|
||||||
settingsLock.Lock()
|
settingsLock.Lock()
|
||||||
defer settingsLock.Unlock()
|
defer settingsLock.Unlock()
|
||||||
@@ -442,15 +442,15 @@ func UpdateSettings(new AppSettings) (AppSettings, error) {
|
|||||||
old.Destemail != new.Destemail ||
|
old.Destemail != new.Destemail ||
|
||||||
//old.Sender != new.Sender {
|
//old.Sender != new.Sender {
|
||||||
old.Maxretry != new.Maxretry {
|
old.Maxretry != new.Maxretry {
|
||||||
new.ReloadNeeded = true
|
new.RestartNeeded = true
|
||||||
} else {
|
} else {
|
||||||
// preserve previous ReloadNeeded if it was already true
|
// preserve previous RestartNeeded if it was already true
|
||||||
new.ReloadNeeded = new.ReloadNeeded || old.ReloadNeeded
|
new.RestartNeeded = new.RestartNeeded || old.RestartNeeded
|
||||||
}
|
}
|
||||||
|
|
||||||
// Countries change? Currently also requires a reload
|
// Countries change? Currently also requires a reload
|
||||||
if !equalStringSlices(old.AlertCountries, new.AlertCountries) {
|
if !equalStringSlices(old.AlertCountries, new.AlertCountries) {
|
||||||
new.ReloadNeeded = true
|
new.RestartNeeded = true
|
||||||
}
|
}
|
||||||
|
|
||||||
currentSettings = new
|
currentSettings = new
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
"nav.dashboard": "Dashboard",
|
"nav.dashboard": "Dashboard",
|
||||||
"nav.filter_debug": "Filter-Debug",
|
"nav.filter_debug": "Filter-Debug",
|
||||||
"nav.settings": "Einstellungen",
|
"nav.settings": "Einstellungen",
|
||||||
"reload_banner.message": "Konfiguration geändert!",
|
"restart_banner.message": "Fail2ban Konfiguration geändert! Um Änderungen zu übernehmen bitte: ",
|
||||||
"reload_banner.button": "Fail2ban neu laden",
|
"restart_banner.button": "Service neu starten",
|
||||||
"dashboard.title": "Dashboard",
|
"dashboard.title": "Dashboard",
|
||||||
"dashboard.overview": "Aktive Jails und Blocks Übersicht",
|
"dashboard.overview": "Aktive Jails und Blocks Übersicht",
|
||||||
"dashboard.search_label": "Suche gesperrte IPs",
|
"dashboard.search_label": "Suche gesperrte IPs",
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
"nav.dashboard": "Dashboard",
|
"nav.dashboard": "Dashboard",
|
||||||
"nav.filter_debug": "Filter Debug",
|
"nav.filter_debug": "Filter Debug",
|
||||||
"nav.settings": "Istellige",
|
"nav.settings": "Istellige",
|
||||||
"reload_banner.message": "D'Konfiguration isch gänderet worde!",
|
"restart_banner.message": "Fail2ban Konfiguration gänderet! Für d'Änderige z'überneh, bitte: ",
|
||||||
"reload_banner.button": "Fail2ban neu lade",
|
"restart_banner.button": "Service neu starte",
|
||||||
"dashboard.title": "Dashboard",
|
"dashboard.title": "Dashboard",
|
||||||
"dashboard.overview": "Übersicht vo de aktive Jails und Blocks",
|
"dashboard.overview": "Übersicht vo de aktive Jails und Blocks",
|
||||||
"dashboard.search_label": "Suech nach g'sperrte IPs",
|
"dashboard.search_label": "Suech nach g'sperrte IPs",
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
"nav.dashboard": "Dashboard",
|
"nav.dashboard": "Dashboard",
|
||||||
"nav.filter_debug": "Filter Debug",
|
"nav.filter_debug": "Filter Debug",
|
||||||
"nav.settings": "Settings",
|
"nav.settings": "Settings",
|
||||||
"reload_banner.message": "Configuration changed!",
|
"restart_banner.message": "Fail2ban configuration changed! To apply the changes, please: ",
|
||||||
"reload_banner.button": "Reload Fail2ban",
|
"restart_banner.button": "Restart Service",
|
||||||
"dashboard.title": "Dashboard",
|
"dashboard.title": "Dashboard",
|
||||||
"dashboard.overview": "Overview active Jails and Blocks",
|
"dashboard.overview": "Overview active Jails and Blocks",
|
||||||
"dashboard.search_label": "Search Banned IPs",
|
"dashboard.search_label": "Search Banned IPs",
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
"nav.dashboard": "Panel de control",
|
"nav.dashboard": "Panel de control",
|
||||||
"nav.filter_debug": "Depuración de filtros",
|
"nav.filter_debug": "Depuración de filtros",
|
||||||
"nav.settings": "Configuración",
|
"nav.settings": "Configuración",
|
||||||
"reload_banner.message": "¡La configuración ha sido modificada!",
|
"restart_banner.message": "¡Configuración de Fail2ban modificada! Para aplicar los cambios, por favor: ",
|
||||||
"reload_banner.button": "Recargar Fail2ban",
|
"restart_banner.button": "Reiniciar servicio",
|
||||||
"dashboard.title": "Panel de control",
|
"dashboard.title": "Panel de control",
|
||||||
"dashboard.overview": "Resumen de Jails y Bloqueos activos",
|
"dashboard.overview": "Resumen de Jails y Bloqueos activos",
|
||||||
"dashboard.search_label": "Buscar IP bloqueadas",
|
"dashboard.search_label": "Buscar IP bloqueadas",
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
"nav.dashboard": "Tableau de bord",
|
"nav.dashboard": "Tableau de bord",
|
||||||
"nav.filter_debug": "Débogage des filtres",
|
"nav.filter_debug": "Débogage des filtres",
|
||||||
"nav.settings": "Paramètres",
|
"nav.settings": "Paramètres",
|
||||||
"reload_banner.message": "Configuration modifiée!",
|
"restart_banner.message": "Configuration Fail2ban modifiée ! Pour appliquer les changements, veuillez: ",
|
||||||
"reload_banner.button": "Recharger Fail2ban",
|
"restart_banner.button": "Redémarrer le service",
|
||||||
"dashboard.title": "Tableau de bord",
|
"dashboard.title": "Tableau de bord",
|
||||||
"dashboard.overview": "Vue d'ensemble des jails et blocages actifs",
|
"dashboard.overview": "Vue d'ensemble des jails et blocages actifs",
|
||||||
"dashboard.search_label": "Rechercher des IP bloquées",
|
"dashboard.search_label": "Rechercher des IP bloquées",
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
"nav.dashboard": "Cruscotto",
|
"nav.dashboard": "Cruscotto",
|
||||||
"nav.filter_debug": "Debug Filtro",
|
"nav.filter_debug": "Debug Filtro",
|
||||||
"nav.settings": "Impostazioni",
|
"nav.settings": "Impostazioni",
|
||||||
"reload_banner.message": "Configurazione modificata!",
|
"restart_banner.message": "Configurazione di Fail2ban modificata! Per applicare le modifiche, per favore: ",
|
||||||
"reload_banner.button": "Ricarica Fail2ban",
|
"restart_banner.button": "Riavvia il servizio",
|
||||||
"dashboard.title": "Cruscotto",
|
"dashboard.title": "Cruscotto",
|
||||||
"dashboard.overview": "Panoramica dei jail e dei blocchi attivi",
|
"dashboard.overview": "Panoramica dei jail e dei blocchi attivi",
|
||||||
"dashboard.search_label": "Cerca IP bloccate",
|
"dashboard.search_label": "Cerca IP bloccate",
|
||||||
|
|||||||
@@ -266,7 +266,7 @@ func SetJailFilterConfigHandler(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Mark reload needed in our UI settings
|
// Mark reload needed in our UI settings
|
||||||
// if err := config.MarkReloadNeeded(); err != nil {
|
// if err := config.MarkRestartNeeded(); err != nil {
|
||||||
// c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
// c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||||
// return
|
// return
|
||||||
// }
|
// }
|
||||||
@@ -276,7 +276,7 @@ func SetJailFilterConfigHandler(c *gin.Context) {
|
|||||||
// Return a simple JSON response without forcing a blocking alert
|
// Return a simple JSON response without forcing a blocking alert
|
||||||
// c.JSON(http.StatusOK, gin.H{
|
// c.JSON(http.StatusOK, gin.H{
|
||||||
// "message": "Filter updated, reload needed",
|
// "message": "Filter updated, reload needed",
|
||||||
// "reloadNeeded": true,
|
// "restartNeeded": true,
|
||||||
// })
|
// })
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -316,7 +316,7 @@ func UpdateJailManagementHandler(c *gin.Context) {
|
|||||||
// c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to reload fail2ban: " + err.Error()})
|
// c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to reload fail2ban: " + err.Error()})
|
||||||
// return
|
// return
|
||||||
//}
|
//}
|
||||||
if err := config.MarkReloadNeeded(); err != nil {
|
if err := config.MarkRestartNeeded(); err != nil {
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -355,8 +355,8 @@ func UpdateSettingsHandler(c *gin.Context) {
|
|||||||
config.DebugLog("Settings updated successfully (handlers.go)")
|
config.DebugLog("Settings updated successfully (handlers.go)")
|
||||||
|
|
||||||
c.JSON(http.StatusOK, gin.H{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"message": "Settings updated",
|
"message": "Settings updated",
|
||||||
"reloadNeeded": newSettings.ReloadNeeded,
|
"restartNeeded": newSettings.RestartNeeded,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -428,8 +428,8 @@ func ApplyFail2banSettings(jailLocalPath string) error {
|
|||||||
return os.WriteFile(jailLocalPath, []byte(content), 0644)
|
return os.WriteFile(jailLocalPath, []byte(content), 0644)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReloadFail2banHandler reloads the Fail2ban service
|
// RestartFail2banHandler reloads the Fail2ban service
|
||||||
func ReloadFail2banHandler(c *gin.Context) {
|
func RestartFail2banHandler(c *gin.Context) {
|
||||||
config.DebugLog("----------------------------")
|
config.DebugLog("----------------------------")
|
||||||
config.DebugLog("ApplyFail2banSettings called (handlers.go)") // entry point
|
config.DebugLog("ApplyFail2banSettings called (handlers.go)") // entry point
|
||||||
|
|
||||||
@@ -439,18 +439,18 @@ func ReloadFail2banHandler(c *gin.Context) {
|
|||||||
// return
|
// return
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// Then reload
|
// Then restart
|
||||||
if err := fail2ban.ReloadFail2ban(); err != nil {
|
if err := fail2ban.RestartFail2ban(); err != nil {
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// We set reload done in config
|
// We set restart done in config
|
||||||
if err := config.MarkReloadDone(); err != nil {
|
if err := config.MarkRestartDone(); err != nil {
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.JSON(http.StatusOK, gin.H{"message": "Fail2ban reloaded successfully"})
|
c.JSON(http.StatusOK, gin.H{"message": "Fail2ban restarted successfully"})
|
||||||
}
|
}
|
||||||
|
|
||||||
// *******************************************************************
|
// *******************************************************************
|
||||||
|
|||||||
@@ -54,8 +54,8 @@ func RegisterRoutes(r *gin.Engine) {
|
|||||||
// TODO: create or generate new filters
|
// TODO: create or generate new filters
|
||||||
// api.POST("/filters/generate", GenerateFilterHandler)
|
// api.POST("/filters/generate", GenerateFilterHandler)
|
||||||
|
|
||||||
// Reload endpoint
|
// Restart endpoint
|
||||||
api.POST("/fail2ban/reload", ReloadFail2banHandler)
|
api.POST("/fail2ban/restart", RestartFail2banHandler)
|
||||||
|
|
||||||
// Handle Fail2Ban notifications
|
// Handle Fail2Ban notifications
|
||||||
api.POST("/ban", BanNotificationHandler)
|
api.POST("/ban", BanNotificationHandler)
|
||||||
|
|||||||
@@ -45,8 +45,8 @@
|
|||||||
height: 4rem;
|
height: 4rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reload banner */
|
/* Restart banner */
|
||||||
#reloadBanner {
|
#restartBanner {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,10 +95,10 @@
|
|||||||
</nav>
|
</nav>
|
||||||
<!-- ******************************************************************* -->
|
<!-- ******************************************************************* -->
|
||||||
|
|
||||||
<!-- Reload Banner -->
|
<!-- Restart Banner -->
|
||||||
<div id="reloadBanner" class="bg-warning text-dark p-3 text-center">
|
<div id="restartBanner" class="bg-warning text-dark p-3 text-center">
|
||||||
<strong data-i18n="reload_banner.message">Configuration changed!</strong>
|
<strong class="p-2" data-i18n="restart_banner.message">Fail2ban configuration changed! To apply the changes, please: </strong>
|
||||||
<button class="btn btn-dark" onclick="reloadFail2ban()" data-i18n="reload_banner.button">Reload Fail2ban</button>
|
<button class="btn btn-dark" onclick="restartFail2ban()" data-i18n="restart_banner.button">Restart Service</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- ******************************************************************* -->
|
<!-- ******************************************************************* -->
|
||||||
@@ -531,7 +531,7 @@
|
|||||||
var currentJailForConfig = null;
|
var currentJailForConfig = null;
|
||||||
window.addEventListener('DOMContentLoaded', function() {
|
window.addEventListener('DOMContentLoaded', function() {
|
||||||
showLoading(true);
|
showLoading(true);
|
||||||
checkReloadNeeded();
|
checkRestartNeeded();
|
||||||
fetchSummary().then(function() {
|
fetchSummary().then(function() {
|
||||||
showLoading(false);
|
showLoading(false);
|
||||||
initializeTooltips(); // Initialize tooltips after fetching and rendering
|
initializeTooltips(); // Initialize tooltips after fetching and rendering
|
||||||
@@ -558,17 +558,17 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if there is still a reload of the fail2ban service needed
|
// Check if there is still a reload of the fail2ban service needed
|
||||||
function checkReloadNeeded() {
|
function checkRestartNeeded() {
|
||||||
fetch('/api/settings')
|
fetch('/api/settings')
|
||||||
.then(res => res.json())
|
.then(res => res.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
if (data.reloadNeeded) {
|
if (data.restartNeeded) {
|
||||||
document.getElementById('reloadBanner').style.display = 'block';
|
document.getElementById('restartBanner').style.display = 'block';
|
||||||
} else {
|
} else {
|
||||||
document.getElementById('reloadBanner').style.display = 'none';
|
document.getElementById('restartBanner').style.display = 'none';
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(err => console.error('Error checking reloadNeeded:', err));
|
.catch(err => console.error('Error checking restartNeeded:', err));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load dynamically the other pages when navigating in nav
|
// Load dynamically the other pages when navigating in nav
|
||||||
@@ -828,11 +828,11 @@
|
|||||||
if (data.error) {
|
if (data.error) {
|
||||||
alert("Error saving config: " + data.error);
|
alert("Error saving config: " + data.error);
|
||||||
} else {
|
} else {
|
||||||
console.log("Filter saved successfully. Reload needed? " + data.reloadNeeded);
|
console.log("Filter saved successfully. Restart needed? " + data.restartNeeded);
|
||||||
var modalEl = document.getElementById('jailConfigModal');
|
var modalEl = document.getElementById('jailConfigModal');
|
||||||
var modalObj = bootstrap.Modal.getInstance(modalEl);
|
var modalObj = bootstrap.Modal.getInstance(modalEl);
|
||||||
modalObj.hide();
|
modalObj.hide();
|
||||||
document.getElementById('reloadBanner').style.display = 'block';
|
document.getElementById('restartBanner').style.display = 'block';
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(function(err) {
|
.catch(function(err) {
|
||||||
@@ -901,7 +901,7 @@
|
|||||||
alert("Error saving jail settings: " + data.error);
|
alert("Error saving jail settings: " + data.error);
|
||||||
} else {
|
} else {
|
||||||
// A restart of fail2ban is needed, to enable or disable jails - a reload is not enough
|
// A restart of fail2ban is needed, to enable or disable jails - a reload is not enough
|
||||||
document.getElementById('reloadBanner').style.display = 'block';
|
document.getElementById('restartBanner').style.display = 'block';
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(function(err) {
|
.catch(function(err) {
|
||||||
@@ -1014,9 +1014,9 @@
|
|||||||
} else {
|
} else {
|
||||||
var selectedLang = $('#languageSelect').val();
|
var selectedLang = $('#languageSelect').val();
|
||||||
loadTranslations(selectedLang);
|
loadTranslations(selectedLang);
|
||||||
console.log("Settings saved successfully. Reload needed? " + data.reloadNeeded);
|
console.log("Settings saved successfully. Restart needed? " + data.restartNeeded);
|
||||||
if (data.reloadNeeded) {
|
if (data.restartNeeded) {
|
||||||
document.getElementById('reloadBanner').style.display = 'block';
|
document.getElementById('restartBanner').style.display = 'block';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -1133,19 +1133,19 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
//*******************************************************************
|
//*******************************************************************
|
||||||
//* Reload fail2ban action : *
|
//* Restart fail2ban action : *
|
||||||
//*******************************************************************
|
//*******************************************************************
|
||||||
|
|
||||||
function reloadFail2ban() {
|
function restartFail2ban() {
|
||||||
if (!confirm("It can happen that some logs are not parsed during the reload of fail2ban. Reload Fail2ban now?")) return;
|
if (!confirm("Keep in mind that while fail2ban is restarting, logs are not being parsed and no IP addresses are blocked. Restart fail2ban now? This will take some time.")) return;
|
||||||
showLoading(true);
|
showLoading(true);
|
||||||
fetch('/api/fail2ban/reload', { method: 'POST' })
|
fetch('/api/fail2ban/restart', { method: 'POST' })
|
||||||
.then(function(res) { return res.json(); })
|
.then(function(res) { return res.json(); })
|
||||||
.then(function(data) {
|
.then(function(data) {
|
||||||
if (data.error) {
|
if (data.error) {
|
||||||
alert("Error: " + data.error);
|
alert("Error: " + data.error);
|
||||||
} else {
|
} else {
|
||||||
document.getElementById('reloadBanner').style.display = 'none';
|
document.getElementById('restartBanner').style.display = 'none';
|
||||||
return fetchSummary();
|
return fetchSummary();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user