From a602207369c4b6b769dc30ff744355d028709e51 Mon Sep 17 00:00:00 2001 From: d3m0k1d Date: Sun, 22 Feb 2026 16:06:51 +0300 Subject: [PATCH] feat: full working max_retry logic --- cmd/banforge/command/daemon.go | 7 ++++++- cmd/banforge/command/rule.go | 3 ++- internal/config/template.go | 2 -- internal/judge/judge.go | 18 +++++++++++++----- internal/storage/requests_db.go | 5 +++-- 5 files changed, 24 insertions(+), 11 deletions(-) diff --git a/cmd/banforge/command/daemon.go b/cmd/banforge/command/daemon.go index 9606d35..e1b70ee 100644 --- a/cmd/banforge/command/daemon.go +++ b/cmd/banforge/command/daemon.go @@ -30,6 +30,11 @@ var DaemonCmd = &cobra.Command{ log.Error("Failed to create request writer", "error", err) os.Exit(1) } + reqDb_r, err := storage.NewRequestsRd() + if err != nil { + log.Error("Failed to create request reader", "error", err) + os.Exit(1) + } banDb_r, err := storage.NewBanReader() if err != nil { log.Error("Failed to create ban reader", "error", err) @@ -63,7 +68,7 @@ var DaemonCmd = &cobra.Command{ log.Error("Failed to load rules", "error", err) os.Exit(1) } - j := judge.New(banDb_r, banDb_w, b, resultCh, entryCh) + j := judge.New(banDb_r, banDb_w, reqDb_r, b, resultCh, entryCh) j.LoadRules(r) go j.UnbanChecker() go j.Tribunal() diff --git a/cmd/banforge/command/rule.go b/cmd/banforge/command/rule.go index 3ee513a..b0c0b7e 100644 --- a/cmd/banforge/command/rule.go +++ b/cmd/banforge/command/rule.go @@ -61,11 +61,12 @@ var ListCmd = &cobra.Command{ } for _, rule := range r { fmt.Printf( - "Name: %s\nService: %s\nPath: %s\nStatus: %s\nMethod: %s\n\n", + "Name: %s\nService: %s\nPath: %s\nStatus: %s\n MaxRetry: %d\nMethod: %s\n\n", rule.Name, rule.ServiceName, rule.Path, rule.Status, + rule.MaxRetry, rule.Method, ) } diff --git a/internal/config/template.go b/internal/config/template.go index 4df0948..21a7fcc 100644 --- a/internal/config/template.go +++ b/internal/config/template.go @@ -12,13 +12,11 @@ config = "/etc/nftables.conf" name = "nginx" logging = "file" log_path = "/var/log/nginx/access.log" -max_retry = 3 enabled = true [[service]] name = "nginx" logging = "journald" log_path = "/var/log/nginx/access.log" -max_retry = 3 enabled = false ` diff --git a/internal/judge/judge.go b/internal/judge/judge.go index df82567..350e677 100644 --- a/internal/judge/judge.go +++ b/internal/judge/judge.go @@ -14,6 +14,7 @@ import ( type Judge struct { db_r *storage.BanReader db_w *storage.BanWriter + db_rq *storage.RequestReader logger *logger.Logger Blocker blocker.BlockerEngine rulesByService map[string][]config.Rule @@ -24,6 +25,7 @@ type Judge struct { func New( db_r *storage.BanReader, db_w *storage.BanWriter, + db_rq *storage.RequestReader, b blocker.BlockerEngine, resultCh chan *storage.LogEntry, entryCh chan *storage.LogEntry, @@ -31,6 +33,7 @@ func New( return &Judge{ db_w: db_w, db_r: db_r, + db_rq: db_rq, logger: logger.New(false), rulesByService: make(map[string][]config.Rule), Blocker: b, @@ -75,11 +78,10 @@ func (j *Judge) Tribunal() { methodMatch := rule.Method == "" || entry.Method == rule.Method statusMatch := rule.Status == "" || entry.Status == rule.Status pathMatch := matchPath(entry.Path, rule.Path) - if methodMatch && statusMatch && pathMatch { ruleMatched = true j.logger.Info("Rule matched", "rule", rule.Name, "ip", entry.IP) - + j.resultCh <- entry banned, err := j.db_r.IsBanned(entry.IP) if err != nil { j.logger.Error("Failed to check ban status", "ip", entry.IP, "error", err) @@ -87,10 +89,17 @@ func (j *Judge) Tribunal() { } if banned { j.logger.Info("IP already banned", "ip", entry.IP) - j.resultCh <- entry break } - + exceeded, err := j.db_rq.IsMaxRetryExceeded(entry.IP, rule.MaxRetry) + if err != nil { + j.logger.Error("Failed to check retry count", "ip", entry.IP, "error", err) + break + } + if !exceeded { + j.logger.Info("Max retry not exceeded", "ip", entry.IP) + break + } err = j.db_w.AddBan(entry.IP, rule.BanTime, rule.Name) if err != nil { j.logger.Error( @@ -118,7 +127,6 @@ func (j *Judge) Tribunal() { "ban_time", rule.BanTime, ) - j.resultCh <- entry break } } diff --git a/internal/storage/requests_db.go b/internal/storage/requests_db.go index ea49298..6a6b67e 100644 --- a/internal/storage/requests_db.go +++ b/internal/storage/requests_db.go @@ -51,12 +51,13 @@ func NewRequestsRd() (*RequestReader, error) { }, nil } -func (r *RequestReader) IsMaxRetryExceeded(ip string, max_retry int) (bool, error) { +func (r *RequestReader) IsMaxRetryExceeded(ip string, maxRetry int) (bool, error) { var count int err := r.db.QueryRow("SELECT COUNT(*) FROM requests WHERE ip = ?", ip).Scan(&count) if err != nil { r.logger.Error("error query count: " + err.Error()) return false, err } - return count >= max_retry, nil + r.logger.Info("Current request count for IP", "ip", ip, "count", count, "maxRetry", maxRetry) + return count >= maxRetry, nil }