fw: allow to configure interception queue number

- Added new configuration field to allow configure fw interception
   number queue (default to 0):
   "FwOptions": {
      "QueueNum": 0
   }
   (we still need to reconfigure nfqueue queues in order for this to
take effect).
 - If the fw configuration path is not supplied, default to
   /etc/opensnitchd/system-fw.json
This commit is contained in:
Gustavo Iñiguez Goia 2024-05-14 23:41:25 +02:00
parent 9afadcb009
commit efc05663eb
Failed to generate hash of commit
8 changed files with 34 additions and 25 deletions

View file

@ -84,14 +84,10 @@ func (c *Common) SetRulesCheckerInterval(interval string) {
// SetQueueNum sets the queue number used by the firewall. // SetQueueNum sets the queue number used by the firewall.
// It's the queue where all intercepted connections will be sent. // It's the queue where all intercepted connections will be sent.
func (c *Common) SetQueueNum(qNum *int) { func (c *Common) SetQueueNum(qNum uint16) {
c.Lock() c.Lock()
defer c.Unlock() defer c.Unlock()
c.QueueNum = qNum
if qNum != nil {
c.QueueNum = uint16(*qNum)
}
} }
// IsRunning returns if the firewall is running or not. // IsRunning returns if the firewall is running or not.

View file

@ -18,6 +18,11 @@ import (
"github.com/fsnotify/fsnotify" "github.com/fsnotify/fsnotify"
) )
var (
// DefaultConfigFile ..
DefaultConfigFile = "/etc/opensnitchd/system-fw.json"
)
// ExprValues holds the statements' options: // ExprValues holds the statements' options:
// "Name": "ct", // "Name": "ct",
// "Values": [ // "Values": [

View file

@ -93,7 +93,7 @@ func (ipt *Iptables) Name() string {
// Init inserts the firewall rules and starts monitoring for firewall // Init inserts the firewall rules and starts monitoring for firewall
// changes. // changes.
func (ipt *Iptables) Init(qNum *int, configPath, monitorInterval string) { func (ipt *Iptables) Init(qNum uint16, configPath, monitorInterval string) {
if ipt.IsRunning() { if ipt.IsRunning() {
return return
} }

View file

@ -71,7 +71,7 @@ func (n *Nft) Name() string {
// Init inserts the firewall rules and starts monitoring for firewall // Init inserts the firewall rules and starts monitoring for firewall
// changes. // changes.
func (n *Nft) Init(qNum *int, configPath, monitorInterval string) { func (n *Nft) Init(qNum uint16, configPath, monitorInterval string) {
if n.IsRunning() { if n.IsRunning() {
return return
} }

View file

@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"github.com/evilsocket/opensnitch/daemon/firewall/common" "github.com/evilsocket/opensnitch/daemon/firewall/common"
"github.com/evilsocket/opensnitch/daemon/firewall/config"
"github.com/evilsocket/opensnitch/daemon/firewall/iptables" "github.com/evilsocket/opensnitch/daemon/firewall/iptables"
"github.com/evilsocket/opensnitch/daemon/firewall/nftables" "github.com/evilsocket/opensnitch/daemon/firewall/nftables"
"github.com/evilsocket/opensnitch/daemon/log" "github.com/evilsocket/opensnitch/daemon/log"
@ -12,11 +13,11 @@ import (
// Firewall is the interface that all firewalls (iptables, nftables) must implement. // Firewall is the interface that all firewalls (iptables, nftables) must implement.
type Firewall interface { type Firewall interface {
Init(*int, string, string) Init(uint16, string, string)
Stop() Stop()
Name() string Name() string
IsRunning() bool IsRunning() bool
SetQueueNum(num *int) SetQueueNum(num uint16)
SaveConfiguration(rawConfig string) error SaveConfiguration(rawConfig string) error
@ -38,18 +39,14 @@ type Firewall interface {
var ( var (
fw Firewall fw Firewall
queueNum = 0 queueNum = uint16(0)
DefaultConfig = "/etc/opensnitchd/system-fw.json"
) )
// Init initializes the firewall and loads firewall rules. // Init initializes the firewall and loads firewall rules.
// We'll try to use the firewall configured in the configuration (iptables/nftables). // We'll try to use the firewall configured in the configuration (iptables/nftables).
// If iptables is not installed, we can add nftables rules directly to the kernel, // If iptables is not installed, we can add nftables rules directly to the kernel,
// without relying on any binaries. // without relying on any binaries.
func Init(fwType, configPath, monitorInterval string, qNum *int) (err error) { func Init(fwType, configPath, monitorInterval string, qNum uint16) (err error) {
if configPath == "" {
configPath = DefaultConfig
}
if fwType == iptables.Name { if fwType == iptables.Name {
fw, err = iptables.Fw() fw, err = iptables.Fw()
if err != nil { if err != nil {
@ -71,9 +68,12 @@ func Init(fwType, configPath, monitorInterval string, qNum *int) (err error) {
if fw == nil { if fw == nil {
return fmt.Errorf("Firewall not initialized") return fmt.Errorf("Firewall not initialized")
} }
if configPath == "" {
configPath = config.DefaultConfigFile
}
fw.Stop() fw.Stop()
fw.Init(qNum, configPath, monitorInterval) fw.Init(qNum, configPath, monitorInterval)
queueNum = *qNum queueNum = qNum
log.Info("Using %s firewall", fw.Name()) log.Info("Using %s firewall", fw.Name())
@ -104,9 +104,9 @@ func CleanRules(logErrors bool) {
} }
// Reload stops current firewall and initializes a new one. // Reload stops current firewall and initializes a new one.
func Reload(fwtype, configPath, monitorInterval string) (err error) { func Reload(fwtype, configPath, monitorInterval string, queueNum uint16) (err error) {
Stop() Stop()
err = Init(fwtype, configPath, monitorInterval, &queueNum) err = Init(fwtype, configPath, monitorInterval, queueNum)
return return
} }

View file

@ -151,19 +151,19 @@ func overwriteLogging() bool {
return debug || warning || important || errorlog || logFile != "" || logMicro return debug || warning || important || errorlog || logFile != "" || logMicro
} }
func setupQueues() { func setupQueues(qNum uint16) {
// prepare the queue // prepare the queue
var err error var err error
queue, err = netfilter.NewQueue(uint16(queueNum)) queue, err = netfilter.NewQueue(qNum)
if err != nil { if err != nil {
msg := fmt.Sprintf("Error creating queue #%d: %s", queueNum, err) msg := fmt.Sprintf("Error creating queue #%d: %s", qNum, err)
uiClient.SendWarningAlert(msg) uiClient.SendWarningAlert(msg)
log.Warning("Is opensnitchd already running?") log.Warning("Is opensnitchd already running?")
log.Fatal(msg) log.Fatal(msg)
} }
pktChan = queue.Packets() pktChan = queue.Packets()
repeatQueueNum = queueNum + 1 repeatQueueNum = int(qNum) + 1
repeatQueue, err = netfilter.NewQueue(uint16(repeatQueueNum)) repeatQueue, err = netfilter.NewQueue(uint16(repeatQueueNum))
if err != nil { if err != nil {
@ -173,6 +173,7 @@ func setupQueues() {
log.Warning(msg) log.Warning(msg)
} }
repeatPktChan = repeatQueue.Packets() repeatPktChan = repeatQueue.Packets()
log.Info("Listening on queue number %d ...", qNum)
} }
func setupLogging() { func setupLogging() {
@ -581,6 +582,10 @@ func main() {
} }
log.Info("Using system fw configuration %s ...", fwConfigFile) log.Info("Using system fw configuration %s ...", fwConfigFile)
if uint16(queueNum) != cfg.FwOptions.QueueNum && queueNum > 0 {
cfg.FwOptions.QueueNum = uint16(queueNum)
}
setupSignals() setupSignals()
log.Info("Loading rules from %s ...", rulesPath) log.Info("Loading rules from %s ...", rulesPath)
@ -596,7 +601,7 @@ func main() {
uiClient = ui.NewClient(uiSocket, configFile, stats, rules, loggerMgr) uiClient = ui.NewClient(uiSocket, configFile, stats, rules, loggerMgr)
setupWorkers() setupWorkers()
setupQueues() setupQueues(cfg.FwOptions.QueueNum)
// queue and firewall rules should be ready by now // queue and firewall rules should be ready by now

View file

@ -58,6 +58,7 @@ type (
ConfigPath string `json:"ConfigPath"` ConfigPath string `json:"ConfigPath"`
BypassQueue string `json:"BypassQueue"` BypassQueue string `json:"BypassQueue"`
MonitorInterval string `json:"MonitorInterval"` MonitorInterval string `json:"MonitorInterval"`
QueueNum uint16 `json:"QueueNum"`
} }
// EbpfOptions struct // EbpfOptions struct

View file

@ -167,6 +167,7 @@ func (c *Client) reloadConfiguration(reload bool, newConfig config.Config) *moni
if c.GetFirewallType() != newConfig.Firewall || if c.GetFirewallType() != newConfig.Firewall ||
newConfig.FwOptions.ConfigPath != c.config.FwOptions.ConfigPath || newConfig.FwOptions.ConfigPath != c.config.FwOptions.ConfigPath ||
newConfig.FwOptions.QueueNum != c.config.FwOptions.QueueNum ||
newConfig.FwOptions.MonitorInterval != c.config.FwOptions.MonitorInterval { newConfig.FwOptions.MonitorInterval != c.config.FwOptions.MonitorInterval {
log.Debug("[config] reloading config.firewall") log.Debug("[config] reloading config.firewall")
@ -174,6 +175,7 @@ func (c *Client) reloadConfiguration(reload bool, newConfig config.Config) *moni
newConfig.Firewall, newConfig.Firewall,
newConfig.FwOptions.ConfigPath, newConfig.FwOptions.ConfigPath,
newConfig.FwOptions.MonitorInterval, newConfig.FwOptions.MonitorInterval,
newConfig.FwOptions.QueueNum,
) )
} else { } else {
log.Debug("[config] config.firewall not changed") log.Debug("[config] config.firewall not changed")