From aacc98668f079c620b9570f16fc8ca92366ecccc Mon Sep 17 00:00:00 2001 From: d3m0k1d Date: Mon, 9 Feb 2026 21:31:19 +0300 Subject: [PATCH] feat: add logic for PortClose and PortOpen on interfaces --- internal/blocker/firewalld.go | 42 ++++++++++++++++++-- internal/blocker/interface.go | 4 +- internal/blocker/iptables.go | 55 +++++++++++++++++++++++++- internal/blocker/nftables.go | 72 ++++++++++++++++++++++++++++++++++- internal/blocker/ufw.go | 35 ++++++++++++++++- 5 files changed, 197 insertions(+), 11 deletions(-) diff --git a/internal/blocker/firewalld.go b/internal/blocker/firewalld.go index 66b3374..a28506d 100644 --- a/internal/blocker/firewalld.go +++ b/internal/blocker/firewalld.go @@ -1,6 +1,7 @@ package blocker import ( + "fmt" "os/exec" "strconv" @@ -59,11 +60,20 @@ func (f *Firewalld) Unban(ip string) error { return nil } -func (f *Firewalld) PortOpen(port int) error { +func (f *Firewalld) PortOpen(port int, protocol string) error { // #nosec G204 - handle is extracted from nftables output and validated if port >= 0 && port <= 65535 { + if protocol != "tcp" && protocol != "udp" { + f.logger.Error("invalid protocol") + return fmt.Errorf("invalid protocol") + } s := strconv.Itoa(port) - cmd := exec.Command("firewall-cmd", "--zone=public", "--add-port="+s+"/tcp", "--permanent") + cmd := exec.Command( + "firewall-cmd", + "--zone=public", + "--add-port="+s+"/"+protocol, + "--permanent", + ) output, err := cmd.CombinedOutput() if err != nil { f.logger.Error(err.Error()) @@ -80,7 +90,33 @@ func (f *Firewalld) PortOpen(port int) error { return nil } -func (f *Firewalld) PortClose(port int) error { +func (f *Firewalld) PortClose(port int, protocol string) error { + // #nosec G204 - handle is extracted from nftables output and validated + if port >= 0 && port <= 65535 { + if protocol != "tcp" && protocol != "udp" { + f.logger.Error("invalid protocol") + return fmt.Errorf("invalid protocol") + } + s := strconv.Itoa(port) + cmd := exec.Command( + "firewall-cmd", + "--zone=public", + "--remove-port="+s+"/"+protocol, + "--permanent", + ) + output, err := cmd.CombinedOutput() + if err != nil { + f.logger.Error(err.Error()) + return err + } + f.logger.Info("Remove port " + s + " " + string(output)) + output, err = exec.Command("firewall-cmd", "--reload").CombinedOutput() + if err != nil { + f.logger.Error(err.Error()) + return err + } + f.logger.Info("Reload " + string(output)) + } return nil } diff --git a/internal/blocker/interface.go b/internal/blocker/interface.go index 4f5a5fe..efe77a9 100644 --- a/internal/blocker/interface.go +++ b/internal/blocker/interface.go @@ -10,8 +10,8 @@ type BlockerEngine interface { Ban(ip string) error Unban(ip string) error Setup(config string) error - PortOpen(port int) error - PortClose(port int) error + PortOpen(port int, protocol string) error + PortClose(port int, protocol string) error } func GetBlocker(fw string, config string) BlockerEngine { diff --git a/internal/blocker/iptables.go b/internal/blocker/iptables.go index fadd96c..d37dc2e 100644 --- a/internal/blocker/iptables.go +++ b/internal/blocker/iptables.go @@ -2,6 +2,7 @@ package blocker import ( "os/exec" + "strconv" "github.com/d3m0k1d/BanForge/internal/logger" ) @@ -102,11 +103,61 @@ func (f *Iptables) Unban(ip string) error { return nil } -func (f *Iptables) PortOpen(port int) error { +func (f *Iptables) PortOpen(port int, protocol string) error { + if port >= 0 && port <= 65535 { + if protocol != "tcp" && protocol != "udp" { + f.logger.Error("invalid protocol") + return nil + } + s := strconv.Itoa(port) + // #nosec G204 - managed by system adminstartor + cmd := exec.Command("iptables", "-A", "INPUT", "-p", protocol, "--dport", s, "-j", "ACCEPT") + output, err := cmd.CombinedOutput() + if err != nil { + f.logger.Error(err.Error()) + return err + } + f.logger.Info("Add port " + s + " " + string(output)) + // #nosec G204 - f.config is validated above via validateConfigPath() + cmd = exec.Command("iptables-save", "-f", f.config) + output, err = cmd.CombinedOutput() + if err != nil { + f.logger.Error("failed to save config", + "config_path", f.config, + "error", err.Error(), + "output", string(output)) + return err + } + } return nil } -func (f *Iptables) PortClose(port int) error { +func (f *Iptables) PortClose(port int, protocol string) error { + if port >= 0 && port <= 65535 { + if protocol != "tcp" && protocol != "udp" { + f.logger.Error("invalid protocol") + return nil + } + s := strconv.Itoa(port) + // #nosec G204 - managed by system adminstartor + cmd := exec.Command("iptables", "-D", "INPUT", "-p", protocol, "--dport", s, "-j", "ACCEPT") + output, err := cmd.CombinedOutput() + if err != nil { + f.logger.Error(err.Error()) + return err + } + f.logger.Info("Add port " + s + " " + string(output)) + // #nosec G204 - f.config is validated above via validateConfigPath() + cmd = exec.Command("iptables-save", "-f", f.config) + output, err = cmd.CombinedOutput() + if err != nil { + f.logger.Error("failed to save config", + "config_path", f.config, + "error", err.Error(), + "output", string(output)) + return err + } + } return nil } diff --git a/internal/blocker/nftables.go b/internal/blocker/nftables.go index 44f14e4..da7ee44 100644 --- a/internal/blocker/nftables.go +++ b/internal/blocker/nftables.go @@ -3,6 +3,7 @@ package blocker import ( "fmt" "os/exec" + "strconv" "strings" "github.com/d3m0k1d/BanForge/internal/logger" @@ -166,11 +167,78 @@ func (n *Nftables) findRuleHandle(ip string) (string, error) { return "", nil } -func (n *Nftables) PortOpen(port int) error { +func (n *Nftables) PortOpen(port int, protocol string) error { + if port >= 0 && port <= 65535 { + if protocol != "tcp" && protocol != "udp" { + n.logger.Error("invalid protocol") + return fmt.Errorf("invalid protocol") + } + s := strconv.Itoa(port) + // #nosec G204 - managed by system adminstartor + cmd := exec.Command( + "nft", + "add", + "rule", + "inet", + "banforge", + "input", + protocol, + "dport", + s, + "accept", + ) + output, err := cmd.CombinedOutput() + if err != nil { + n.logger.Error(err.Error()) + return err + } + n.logger.Info("Add port " + s + " " + string(output)) + err = saveNftablesConfig(n.config) + if err != nil { + n.logger.Error("failed to save config", + "config_path", n.config, + "error", err.Error()) + return err + } + } return nil } -func (n *Nftables) PortClose(port int) error { +func (n *Nftables) PortClose(port int, protocol string) error { + if port >= 0 && port <= 65535 { + if protocol != "tcp" && protocol != "udp" { + n.logger.Error("invalid protocol") + return fmt.Errorf("invalid protocol") + } + s := strconv.Itoa(port) + // #nosec G204 - managed by system adminstartor + cmd := exec.Command( + "nft", + "add", + "rule", + "inet", + "banforge", + "input", + protocol, + "dport", + s, + "drop", + ) + output, err := cmd.CombinedOutput() + if err != nil { + n.logger.Error(err.Error()) + return err + } + n.logger.Info("Add port " + s + " " + string(output)) + err = saveNftablesConfig(n.config) + if err != nil { + n.logger.Error("failed to save config", + "config_path", n.config, + "error", err.Error()) + return err + } + + } return nil } diff --git a/internal/blocker/ufw.go b/internal/blocker/ufw.go index b7fbf33..a8739fc 100644 --- a/internal/blocker/ufw.go +++ b/internal/blocker/ufw.go @@ -3,6 +3,7 @@ package blocker import ( "fmt" "os/exec" + "strconv" "github.com/d3m0k1d/BanForge/internal/logger" ) @@ -56,11 +57,41 @@ func (u *Ufw) Unban(ip string) error { return nil } -func (u *Ufw) PortOpen(port int) error { +func (u *Ufw) PortOpen(port int, protocol string) error { + if port >= 0 && port <= 65535 { + if protocol != "tcp" && protocol != "udp" { + u.logger.Error("invalid protocol") + return fmt.Errorf("invalid protocol") + } + s := strconv.Itoa(port) + // #nosec G204 - managed by system adminstartor + cmd := exec.Command("ufw", "allow", s+"/"+protocol) + output, err := cmd.CombinedOutput() + if err != nil { + u.logger.Error(err.Error()) + return err + } + u.logger.Info("Add port " + s + " " + string(output)) + } return nil } -func (u *Ufw) PortClose(port int) error { +func (u *Ufw) PortClose(port int, protocol string) error { + if port >= 0 && port <= 65535 { + if protocol != "tcp" && protocol != "udp" { + u.logger.Error("invalid protocol") + return nil + } + s := strconv.Itoa(port) + // #nosec G204 - managed by system adminstartor + cmd := exec.Command("ufw", "deny", s+"/"+protocol) + output, err := cmd.CombinedOutput() + if err != nil { + u.logger.Error(err.Error()) + return err + } + u.logger.Info("Add port " + s + " " + string(output)) + } return nil }