workaround for the restart command may fail in container (since fail2ban runs on the host)

This commit is contained in:
2025-02-27 14:03:08 +01:00
parent 9a66d2c87a
commit 8c84909c95
3 changed files with 27 additions and 29 deletions

View File

@@ -191,6 +191,8 @@ func initializeFromJailFile() error {
// initializeFail2banAction writes a custom action configuration for Fail2ban to use AlertCountries. // initializeFail2banAction writes a custom action configuration for Fail2ban to use AlertCountries.
func initializeFail2banAction() error { func initializeFail2banAction() error {
DebugLog("----------------------------")
DebugLog("Running initial initializeFail2banAction()") // entry point
// Ensure the jail.local is configured correctly // Ensure the jail.local is configured correctly
if err := setupGeoCustomAction(); err != nil { if err := setupGeoCustomAction(); err != nil {
fmt.Println("Error setup GeoCustomAction in jail.local:", err) fmt.Println("Error setup GeoCustomAction in jail.local:", err)
@@ -205,6 +207,7 @@ func initializeFail2banAction() error {
// setupGeoCustomAction checks and replaces the default action in jail.local with our from fail2ban-UI // setupGeoCustomAction checks and replaces the default action in jail.local with our from fail2ban-UI
func setupGeoCustomAction() error { func setupGeoCustomAction() error {
DebugLog("Running initial setupGeoCustomAction()") // entry point
file, err := os.Open(jailFile) file, err := os.Open(jailFile)
if err != nil { if err != nil {
// Fallback: Copy default file if jail.local is not found // Fallback: Copy default file if jail.local is not found
@@ -284,6 +287,7 @@ func copyFile(src, dst string) error {
// ensureJailDConfig checks if the jail.d file exists and creates it if necessary // ensureJailDConfig checks if the jail.d file exists and creates it if necessary
func ensureJailDConfig() error { func ensureJailDConfig() error {
DebugLog("Running initial ensureJailDConfig()") // entry point
// Check if the file already exists // Check if the file already exists
if _, err := os.Stat(jailDFile); err == nil { if _, err := os.Stat(jailDFile); err == nil {
// File already exists, do nothing // File already exists, do nothing
@@ -310,6 +314,8 @@ action_mwlg = %(action_)s
// writeFail2banAction creates or updates the action file with the AlertCountries. // writeFail2banAction creates or updates the action file with the AlertCountries.
func writeFail2banAction() error { func writeFail2banAction() error {
DebugLog("Running initial writeFail2banAction()") // entry point
DebugLog("----------------------------")
// Define the Fail2Ban action file content // Define the Fail2Ban action file content
actionConfig := `[INCLUDES] actionConfig := `[INCLUDES]
@@ -395,7 +401,7 @@ func saveSettings() error {
if err != nil { if err != nil {
DebugLog("Error writing to file: %v", err) // Debug DebugLog("Error writing to file: %v", err) // Debug
} }
// Update the Fail2ban action file // Write again the Fail2ban-UI action file (in the future not used anymore)
return writeFail2banAction() return writeFail2banAction()
} }
@@ -439,8 +445,6 @@ func UpdateSettings(new AppSettings) (AppSettings, error) {
old.Bantime != new.Bantime || old.Bantime != new.Bantime ||
old.Findtime != new.Findtime || old.Findtime != new.Findtime ||
//old.Maxretry != new.Maxretry || //old.Maxretry != new.Maxretry ||
old.Destemail != new.Destemail ||
//old.Sender != new.Sender {
old.Maxretry != new.Maxretry { old.Maxretry != new.Maxretry {
new.RestartNeeded = true new.RestartNeeded = true
} else { } else {
@@ -448,11 +452,6 @@ func UpdateSettings(new AppSettings) (AppSettings, error) {
new.RestartNeeded = new.RestartNeeded || old.RestartNeeded new.RestartNeeded = new.RestartNeeded || old.RestartNeeded
} }
// Countries change? Currently also requires a reload
if !equalStringSlices(old.AlertCountries, new.AlertCountries) {
new.RestartNeeded = true
}
currentSettings = new currentSettings = new
DebugLog("New settings applied: %v", currentSettings) // Log settings applied DebugLog("New settings applied: %v", currentSettings) // Log settings applied
@@ -464,19 +463,3 @@ func UpdateSettings(new AppSettings) (AppSettings, error) {
fmt.Println("Settings saved to file successfully") // Log save success fmt.Println("Settings saved to file successfully") // Log save success
return currentSettings, nil return currentSettings, nil
} }
func equalStringSlices(a, b []string) bool {
if len(a) != len(b) {
return false
}
m := make(map[string]bool)
for _, x := range a {
m[x] = false
}
for _, x := range b {
if _, ok := m[x]; !ok {
return false
}
}
return true
}

View File

@@ -19,6 +19,7 @@ package fail2ban
import ( import (
"errors" "errors"
"fmt" "fmt"
"os"
"os/exec" "os/exec"
"strings" "strings"
"time" "time"
@@ -152,6 +153,11 @@ func ReloadFail2ban() error {
// RestartFail2ban restarts the Fail2ban service. // RestartFail2ban restarts the Fail2ban service.
func RestartFail2ban() error { func RestartFail2ban() error {
// Check if running inside a container.
if _, container := os.LookupEnv("CONTAINER"); container {
return fmt.Errorf("restart not supported inside container; please restart fail2ban on the host")
}
cmd := "systemctl restart fail2ban" cmd := "systemctl restart fail2ban"
out, err := execCommand(cmd) out, err := execCommand(cmd)
if err != nil { if err != nil {

View File

@@ -439,13 +439,22 @@ func RestartFail2banHandler(c *gin.Context) {
// return // return
// } // }
// Then restart // Attempt to restart the fail2ban service.
if err := fail2ban.RestartFail2ban(); err != nil { restartErr := fail2ban.RestartFail2ban()
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) if restartErr != nil {
return // Check if running inside a container.
if _, container := os.LookupEnv("CONTAINER"); container {
// In a container, the restart command may fail (since fail2ban runs on the host).
// Log the error and continue, so we can mark the restart as done.
log.Printf("Warning: restart failed inside container (expected behavior): %v", restartErr)
} else {
// On the host, a restart error is not acceptable.
c.JSON(http.StatusInternalServerError, gin.H{"error": restartErr.Error()})
return
}
} }
// We set restart done in config // Only call MarkRestartDone if we either successfully restarted the service or we are in a container.
if err := config.MarkRestartDone(); 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