From 6ebda7673811340542f1109bd2b42a54860fc4b9 Mon Sep 17 00:00:00 2001 From: d3m0k1d Date: Tue, 27 Jan 2026 16:59:32 +0300 Subject: [PATCH] feat: Add apache support --- cmd/banforge/command/daemon.go | 11 +++++- internal/parser/ApacheParser.go | 60 +++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 internal/parser/ApacheParser.go diff --git a/cmd/banforge/command/daemon.go b/cmd/banforge/command/daemon.go index 86efb04..d152c01 100644 --- a/cmd/banforge/command/daemon.go +++ b/cmd/banforge/command/daemon.go @@ -112,6 +112,11 @@ var DaemonCmd = &cobra.Command{ ssh := parser.NewSshdParser() ssh.Parse(p.Events(), entryCh) } + if svc.Name == "apache" { + log.Info("Starting apache parser", "service", serviceName) + ap := parser.NewApacheParser() + ap.Parse(p.Events(), entryCh) + } }(pars, svc.Name) continue } @@ -138,7 +143,11 @@ var DaemonCmd = &cobra.Command{ log.Info("Starting ssh parser", "service", serviceName) ssh := parser.NewSshdParser() ssh.Parse(p.Events(), resultCh) - + } + if svc.Name == "apache" { + log.Info("Starting apache parser", "service", serviceName) + ap := parser.NewApacheParser() + ap.Parse(p.Events(), resultCh) } }(pars, svc.Name) diff --git a/internal/parser/ApacheParser.go b/internal/parser/ApacheParser.go new file mode 100644 index 0000000..6d38d24 --- /dev/null +++ b/internal/parser/ApacheParser.go @@ -0,0 +1,60 @@ +package parser + +import ( + "github.com/d3m0k1d/BanForge/internal/logger" + "github.com/d3m0k1d/BanForge/internal/storage" + "regexp" +) + +type ApacheParser struct { + pattern *regexp.Regexp + logger *logger.Logger +} + +func NewApacheParser() *ApacheParser { + pattern := regexp.MustCompile( + `^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\s+-\s+-\s+\[(.*?)\]\s+"(\w+)\s+(.*?)\s+HTTP/[\d.]+"\s+(\d+)\s+(\d+|-)\s+"(.*?)"\s+"(.*?)"`, + ) + // Groups: + // 1: IP + // 2: Timestamp + // 3: Method (GET, POST, etc.) + // 4: Path + // 5: Status Code (200, 404, 403...) + // 6: Response Size + // 7: Referer + // 8: User-Agent + + return &ApacheParser{ + pattern: pattern, + logger: logger.New(false), + } +} + +func (p *ApacheParser) Parse(eventCh <-chan Event, resultCh chan<- *storage.LogEntry) { + // Group 1: IP, Group 2: Timestamp, Group 3: Method, Group 4: Path, Group 5: Status + for event := range eventCh { + matches := p.pattern.FindStringSubmatch(event.Data) + if matches == nil { + continue + } + path := matches[4] + status := matches[5] + method := matches[3] + + resultCh <- &storage.LogEntry{ + Service: "apache", + IP: matches[1], + Path: path, + Status: status, + Method: method, + } + p.logger.Info( + "Parsed apache log entry", + "ip", matches[1], + "path", path, + "status", status, + "method", method, + ) + } +}