From 3d86e087b25238bd9bf154f3f5330e9e9051fa0e Mon Sep 17 00:00:00 2001 From: root Date: Wed, 19 Feb 2025 14:12:45 +0100 Subject: [PATCH 1/3] Make server-port configurable --- cmd/server/main.go | 18 ++++++++++-------- internal/config/settings.go | 13 +++++++++---- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/cmd/server/main.go b/cmd/server/main.go index c9127a4..04437e0 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -4,6 +4,7 @@ import ( "fmt" "log" "os" + "strconv" "time" "github.com/gin-gonic/gin" @@ -24,6 +25,7 @@ func main() { // Create a new Gin router. router := gin.Default() + serverPort := strconv.Itoa(int(settings.Port)) // Load HTML templates depending on whether the application is running inside a container. _, container := os.LookupEnv("CONTAINER") @@ -38,18 +40,18 @@ func main() { // Register all application routes, including the static file serving route for locales. web.RegisterRoutes(router) - printWelcomeBanner() + printWelcomeBanner(serverPort) log.Println("--- Fail2Ban-UI started in", gin.Mode(), "mode ---") - log.Println("Server listening on port :8080.") + log.Println("Server listening on port", serverPort, ".") // Start the server on port 8080. - if err := router.Run(":8080"); err != nil { + if err := router.Run(":", serverPort); err != nil { log.Fatalf("Server crashed: %v", err) } } // printWelcomeBanner prints a cool Tux banner with startup info. -func printWelcomeBanner() { +func printWelcomeBanner(appPort string) { greeting := getGreeting() const tuxBanner = ` .--. @@ -62,13 +64,13 @@ func printWelcomeBanner() { Fail2Ban UI - A Swissmade Management Interface ---------------------------------------------- -Developers: https://swissmakers.ch -Mode: %s -Listening on: http://0.0.0.0:8080 +Developers: https://swissmakers.ch +Mode: %s +Listening on: http://0.0.0.0:%s ---------------------------------------------- ` - fmt.Printf(tuxBanner, greeting, gin.Mode()) + fmt.Printf(tuxBanner, greeting, gin.Mode(), appPort) } // getGreeting returns a friendly greeting based on the time of day. diff --git a/internal/config/settings.go b/internal/config/settings.go index 10d2154..d666939 100644 --- a/internal/config/settings.go +++ b/internal/config/settings.go @@ -40,6 +40,7 @@ type SMTPSettings struct { // AppSettings holds the main UI settings and Fail2ban configuration type AppSettings struct { Language string `json:"language"` + Port int `json:"port"` Debug bool `json:"debug"` ReloadNeeded bool `json:"reloadNeeded"` AlertCountries []string `json:"alertCountries"` @@ -57,10 +58,11 @@ type AppSettings struct { // init paths to key-files const ( - settingsFile = "fail2ban-ui-settings.json" // this is relative to where the app was started - jailFile = "/etc/fail2ban/jail.local" // Path to jail.local (to override conf-values from jail.conf) - jailDFile = "/etc/fail2ban/jail.d/ui-custom-action.conf" - actionFile = "/etc/fail2ban/action.d/ui-custom-action.conf" + settingsFile = "fail2ban-ui-settings.json" // this is relative to where the app was started + defaultjailFile = "/etc/fail2ban/jail.conf" + jailFile = "/etc/fail2ban/jail.local" // Path to jail.local (to override conf-values from jail.conf) + jailDFile = "/etc/fail2ban/jail.d/ui-custom-action.conf" + actionFile = "/etc/fail2ban/action.d/ui-custom-action.conf" ) // in-memory copy of settings @@ -97,6 +99,9 @@ func setDefaults() { if currentSettings.Language == "" { currentSettings.Language = "en" } + if currentSettings.Port == 0 { + currentSettings.Port = 8080 + } if currentSettings.AlertCountries == nil { currentSettings.AlertCountries = []string{"ALL"} } From e17760f93a7cead75f8fd2f09a87ec098661f32c Mon Sep 17 00:00:00 2001 From: root Date: Wed, 19 Feb 2025 14:30:47 +0100 Subject: [PATCH 2/3] Add hook, if no jail.local was precreated and fix bug on server start --- cmd/server/main.go | 4 ++-- internal/config/settings.go | 37 ++++++++++++++++++++++++++++++++++--- 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/cmd/server/main.go b/cmd/server/main.go index 04437e0..75af774 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -45,8 +45,8 @@ func main() { log.Println("Server listening on port", serverPort, ".") // Start the server on port 8080. - if err := router.Run(":", serverPort); err != nil { - log.Fatalf("Server crashed: %v", err) + if err := router.Run(":" + serverPort); err != nil { + log.Fatalf("Could not start server: %v\n", err) } } diff --git a/internal/config/settings.go b/internal/config/settings.go index d666939..27fba0e 100644 --- a/internal/config/settings.go +++ b/internal/config/settings.go @@ -20,6 +20,7 @@ import ( "bufio" "encoding/json" "fmt" + "io" "os" "regexp" "strconv" @@ -58,8 +59,8 @@ type AppSettings struct { // init paths to key-files const ( - settingsFile = "fail2ban-ui-settings.json" // this is relative to where the app was started - defaultjailFile = "/etc/fail2ban/jail.conf" + settingsFile = "fail2ban-ui-settings.json" // this file is created, relatively to where the app was started + defaultJailFile = "/etc/fail2ban/jail.conf" jailFile = "/etc/fail2ban/jail.local" // Path to jail.local (to override conf-values from jail.conf) jailDFile = "/etc/fail2ban/jail.d/ui-custom-action.conf" actionFile = "/etc/fail2ban/action.d/ui-custom-action.conf" @@ -206,7 +207,19 @@ func initializeFail2banAction() error { func setupGeoCustomAction() error { file, err := os.Open(jailFile) if err != nil { - return err // File not found or inaccessible + // Fallback: Copy default file if jail.local is not found + if os.IsNotExist(err) { + if err := copyFile(defaultJailFile, jailFile); err != nil { + return fmt.Errorf("failed to copy default jail.conf to jail.local: %w", err) + } + fmt.Println("Successfully created jail.local from jail.conf.") + file, err = os.Open(jailFile) + if err != nil { + return err + } + } else { + return err // Other error + } } defer file.Close() @@ -251,6 +264,24 @@ func setupGeoCustomAction() error { return os.WriteFile(jailFile, []byte(output), 0644) } +// copyFile copies a file from src to dst. If the destination file does not exist, it will be created. +func copyFile(src, dst string) error { + sourceFile, err := os.Open(src) + if err != nil { + return err + } + defer sourceFile.Close() + + destFile, err := os.Create(dst) + if err != nil { + return err + } + defer destFile.Close() + + _, err = io.Copy(destFile, sourceFile) + return err +} + // ensureJailDConfig checks if the jail.d file exists and creates it if necessary func ensureJailDConfig() error { // Check if the file already exists From 96753848758b14352d02eb29f68675592808ee7d Mon Sep 17 00:00:00 2001 From: root Date: Wed, 19 Feb 2025 14:50:58 +0100 Subject: [PATCH 3/3] change fail2ban service not running error --- internal/fail2ban/client.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/fail2ban/client.go b/internal/fail2ban/client.go index 654aa8b..546ff7e 100644 --- a/internal/fail2ban/client.go +++ b/internal/fail2ban/client.go @@ -37,7 +37,7 @@ func GetJails() ([]string, error) { cmd := exec.Command("fail2ban-client", "status") out, err := cmd.CombinedOutput() if err != nil { - return nil, fmt.Errorf("could not get jail information. is fail2ban running? error: %v", err) + return nil, fmt.Errorf("error: unable to retrieve jail information. is your fail2ban service running? details: %v", err) } var jails []string