diff --git a/daemon/core/ebpf.go b/daemon/core/ebpf.go index bf0a2adbac..c63a4e78f0 100644 --- a/daemon/core/ebpf.go +++ b/daemon/core/ebpf.go @@ -7,9 +7,9 @@ import ( "github.com/iovisor/gobpf/elf" ) -// LoadEbpfModule loads the given eBPF module -// It'll try to load from several paths. -func LoadEbpfModule(module string) (m *elf.Module, err error) { +// LoadEbpfModule loads the given eBPF module, from the given path if specified. +// Otherwise t'll try to load the module from several default paths. +func LoadEbpfModule(module, path string) (m *elf.Module, err error) { var ( modulesDir = "/opensnitchd/ebpf" paths = []string{ @@ -18,6 +18,12 @@ func LoadEbpfModule(module string) (m *elf.Module, err error) { fmt.Sprint("/etc/opensnitchd"), // Deprecated: will be removed in future versions. } ) + + // if path has been specified, try to load the module from there. + if path != "" { + paths = []string{path} + } + modulePath := "" moduleError := fmt.Errorf(`Module not found (%s) in any of the paths. You may need to install the corresponding package`, module) diff --git a/daemon/dns/ebpfhook.go b/daemon/dns/ebpfhook.go index abc5ecc0fb..ae470b9915 100644 --- a/daemon/dns/ebpfhook.go +++ b/daemon/dns/ebpfhook.go @@ -93,8 +93,8 @@ func lookupSymbol(elffile *elf.File, symbolName string) (uint64, error) { } // ListenerEbpf starts listening for DNS events. -func ListenerEbpf() error { - m, err := core.LoadEbpfModule("opensnitch-dns.o") +func ListenerEbpf(ebpfModPath string) error { + m, err := core.LoadEbpfModule("opensnitch-dns.o", ebpfModPath) if err != nil { log.Error("[eBPF DNS]: %s", err) return err diff --git a/daemon/firewall/common/common.go b/daemon/firewall/common/common.go index 017cfa8e2f..9c8589406e 100644 --- a/daemon/firewall/common/common.go +++ b/daemon/firewall/common/common.go @@ -138,7 +138,7 @@ func (c *Common) NewRulesChecker(areRulesLoaded callbackBool, reloadRules callba } } c.stopChecker = make(chan bool, 1) - log.Info("Starting new fw checker every %s ...", DefaultCheckInterval) + log.Info("Starting new fw checker every %s ...", c.RulesCheckInterval) c.RulesChecker = time.NewTicker(c.RulesCheckInterval) go startCheckingRules(c.stopChecker, c.RulesChecker, areRulesLoaded, reloadRules) diff --git a/daemon/main.go b/daemon/main.go index e04af2edd9..daec256829 100644 --- a/daemon/main.go +++ b/daemon/main.go @@ -64,6 +64,7 @@ var ( rulesPath = "/etc/opensnitchd/rules/" configFile = "/etc/opensnitchd/default-config.json" fwConfigFile = "/etc/opensnitchd/system-fw.json" + ebpfModPath = "" // /usr/lib/opensnitchd/ebpf noLiveReload = false queueNum = 0 repeatQueueNum int //will be set later to queueNum + 1 @@ -100,13 +101,14 @@ func init() { flag.StringVar(&procmonMethod, "process-monitor-method", procmonMethod, "How to search for processes path. Options: ftrace, audit (experimental), ebpf (experimental), proc (default)") flag.StringVar(&uiSocket, "ui-socket", uiSocket, "Path the UI gRPC service listener (https://github.com/grpc/grpc/blob/master/doc/naming.md).") - flag.StringVar(&rulesPath, "rules-path", rulesPath, "Path to load JSON rules from.") flag.IntVar(&queueNum, "queue-num", queueNum, "Netfilter queue number.") flag.IntVar(&workers, "workers", workers, "Number of concurrent workers.") flag.BoolVar(&noLiveReload, "no-live-reload", debug, "Disable rules live reloading.") + flag.StringVar(&rulesPath, "rules-path", rulesPath, "Path to load JSON rules from.") flag.StringVar(&configFile, "config-file", configFile, "Path to the daemon configuration file.") flag.StringVar(&fwConfigFile, "fw-config-file", fwConfigFile, "Path to the system fw configuration file.") + //flag.StringVar(&ebpfModPath, "ebpf-modules-path", ebpfModPath, "Path to the directory with the eBPF modules.") flag.StringVar(&logFile, "log-file", logFile, "Write logs to this file instead of the standard output.") flag.BoolVar(&logUTC, "log-utc", logUTC, "Write logs output with UTC timezone (enabled by default).") flag.BoolVar(&logMicro, "log-micro", logMicro, "Write logs output with microsecond timestamp (disabled by default).") @@ -582,15 +584,15 @@ func main() { // overwrite monitor method from configuration if the user has passed // the option via command line. if procmonMethod != "" { - if err := monitor.ReconfigureMonitorMethod(procmonMethod); err != nil { + if err := monitor.ReconfigureMonitorMethod(procmonMethod, cfg.Ebpf.ModulesPath); err != nil { msg := fmt.Sprintf("Unable to set process monitor method via parameter: %v", err) uiClient.SendWarningAlert(msg) log.Warning(msg) } } - go func(uiClient *ui.Client) { - if err := dns.ListenerEbpf(); err != nil { + go func(uiClient *ui.Client, ebpfPath string) { + if err := dns.ListenerEbpf(ebpfPath); err != nil { msg := fmt.Sprintf("EBPF-DNS: Unable to attach ebpf listener: %s", err) log.Warning(msg) // don't display an alert, since this module is not critical @@ -602,7 +604,7 @@ func main() { msg) } - }(uiClient) + }(uiClient, ebpfModPath) initSystemdResolvedMonitor() diff --git a/daemon/procmon/ebpf/ebpf.go b/daemon/procmon/ebpf/ebpf.go index a3e0c47a36..5ad83f7106 100644 --- a/daemon/procmon/ebpf/ebpf.go +++ b/daemon/procmon/ebpf/ebpf.go @@ -52,10 +52,12 @@ type Error struct { } var ( - m, perfMod *elf.Module - lock = sync.RWMutex{} - mapSize = uint(12000) - ebpfMaps map[string]*ebpfMapsForProto + m, perfMod *elf.Module + lock = sync.RWMutex{} + mapSize = uint(12000) + ebpfMaps map[string]*ebpfMapsForProto + modulesPath string + //connections which were established at the time when opensnitch started alreadyEstablished = alreadyEstablishedConns{ TCP: make(map[*daemonNetlink.Socket]int), @@ -75,7 +77,9 @@ var ( ) //Start installs ebpf kprobes -func Start() *Error { +func Start(modPath string) *Error { + modulesPath = modPath + setRunning(false) if err := mountDebugFS(); err != nil { return &Error{ @@ -84,7 +88,7 @@ func Start() *Error { } } var err error - m, err = core.LoadEbpfModule("opensnitch.o") + m, err = core.LoadEbpfModule("opensnitch.o", modulesPath) if err != nil { dispatchErrorEvent(fmt.Sprint("[eBPF]: ", err.Error())) return &Error{NotAvailable, fmt.Errorf("[eBPF] Error loading opensnitch.o: %s", err.Error())} diff --git a/daemon/procmon/ebpf/events.go b/daemon/procmon/ebpf/events.go index 85c48298e4..6c81d1b021 100644 --- a/daemon/procmon/ebpf/events.go +++ b/daemon/procmon/ebpf/events.go @@ -75,7 +75,7 @@ func initEventsStreamer() *Error { elfOpts := make(map[string]elf.SectionParams) elfOpts["maps/"+perfMapName] = elf.SectionParams{PerfRingBufferPageCount: ringBuffSize} var err error - perfMod, err = core.LoadEbpfModule("opensnitch-procs.o") + perfMod, err = core.LoadEbpfModule("opensnitch-procs.o", modulesPath) if err != nil { dispatchErrorEvent(fmt.Sprint("[eBPF events]: ", err)) return &Error{EventsNotAvailable, err} diff --git a/daemon/procmon/monitor/init.go b/daemon/procmon/monitor/init.go index f66577e28e..d261409400 100644 --- a/daemon/procmon/monitor/init.go +++ b/daemon/procmon/monitor/init.go @@ -50,7 +50,7 @@ func stopProcMonitors() { } // ReconfigureMonitorMethod configures a new method for parsing connections. -func ReconfigureMonitorMethod(newMonitorMethod string) *Error { +func ReconfigureMonitorMethod(newMonitorMethod, ebpfModulesPath string) *Error { if procmon.GetMonitorMethod() == newMonitorMethod { return nil } @@ -64,7 +64,7 @@ func ReconfigureMonitorMethod(newMonitorMethod string) *Error { // if the new monitor method fails to start, rollback the change and exit // without saving the configuration. Otherwise we can end up with the wrong // monitor method configured and saved to file. - err := Init() + err := Init(ebpfModulesPath) if err.What > NoError { log.Error("Reconf() -> Init() error: %v", err) procmon.SetMonitorMethod(oldMethod) @@ -85,7 +85,7 @@ func End() { } // Init starts parsing connections using the method specified. -func Init() (errm *Error) { +func Init(ebpfModulesPath string) (errm *Error) { errm = &Error{} if cacheMonitorsRunning == false { @@ -94,7 +94,7 @@ func Init() (errm *Error) { } if procmon.MethodIsEbpf() { - err := ebpf.Start() + err := ebpf.Start(ebpfModulesPath) if err == nil { log.Info("Process monitor method ebpf") return errm diff --git a/daemon/ui/config/config.go b/daemon/ui/config/config.go index 37a1ce2c83..2645612b49 100644 --- a/daemon/ui/config/config.go +++ b/daemon/ui/config/config.go @@ -13,60 +13,67 @@ import ( "github.com/evilsocket/opensnitch/daemon/statistics" ) -type serverTLSOptions struct { - CACert string `json:"CACert"` - ServerCert string `json:"ServerCert"` - ServerKey string `json:"ServerKey"` - ClientCert string `json:"ClientCert"` - ClientKey string `json:"ClientKey"` - // https://pkg.go.dev/crypto/tls#Config - SkipVerify bool `json:"SkipVerify"` - //https://pkg.go.dev/crypto/tls#ClientAuthType - ClientAuthType string `json:"ClientAuthType"` +type ( + serverTLSOptions struct { + CACert string `json:"CACert"` + ServerCert string `json:"ServerCert"` + ServerKey string `json:"ServerKey"` + ClientCert string `json:"ClientCert"` + ClientKey string `json:"ClientKey"` + // https://pkg.go.dev/crypto/tls#Config + SkipVerify bool `json:"SkipVerify"` + // https://pkg.go.dev/crypto/tls#ClientAuthType + ClientAuthType string `json:"ClientAuthType"` - // https://pkg.go.dev/crypto/tls#Conn.VerifyHostname - //VerifyHostname bool - // https://pkg.go.dev/crypto/tls#example-Config-VerifyConnection - // VerifyConnection bool - // VerifyPeerCertificate bool -} + // https://pkg.go.dev/crypto/tls#Conn.VerifyHostname + // VerifyHostname bool + // https://pkg.go.dev/crypto/tls#example-Config-VerifyConnection + // VerifyConnection bool + // VerifyPeerCertificate bool + } -type serverAuth struct { - // token?, google?, simple-tls, mutual-tls - Type string `json:"Type"` - TLSOptions serverTLSOptions `json:"TLSOptions"` -} + serverAuth struct { + // token?, google?, simple-tls, mutual-tls + Type string `json:"Type"` + TLSOptions serverTLSOptions `json:"TLSOptions"` + } -type serverConfig struct { - Address string `json:"Address"` - Authentication serverAuth `json:"Authentication"` - LogFile string `json:"LogFile"` - Loggers []loggers.LoggerConfig `json:"Loggers"` -} + serverConfig struct { + Address string `json:"Address"` + Authentication serverAuth `json:"Authentication"` + LogFile string `json:"LogFile"` + Loggers []loggers.LoggerConfig `json:"Loggers"` + } -type rulesOptions struct { - Path string `json:"Path"` - EnableChecksums bool `json:"EnableChecksums"` -} + rulesOptions struct { + Path string `json:"Path"` + EnableChecksums bool `json:"EnableChecksums"` + } -type fwOptions struct { - Firewall string `json:"Firewall"` - ConfigPath string `json:"ConfigPath"` - ActionOnOverflow string `json:"ActionOnOverflow"` - MonitorInterval string `json:"MonitorInterval"` -} + fwOptions struct { + Firewall string `json:"Firewall"` + ConfigPath string `json:"ConfigPath"` + BypassQueue string `json:"BypassQueue"` + MonitorInterval string `json:"MonitorInterval"` + } + + ebpfOptions struct { + ModulesPath string `json:"ModulesPath"` + } +) // Config holds the values loaded from configFile type Config struct { sync.RWMutex Server serverConfig `json:"Server"` Stats statistics.StatsConfig `json:"Stats"` + Rules rulesOptions `json:"Rules"` + Ebpf ebpfOptions `json:"Ebpf"` + FwOptions fwOptions `json:"FwOptions"` DefaultAction string `json:"DefaultAction"` DefaultDuration string `json:"DefaultDuration"` ProcMonitorMethod string `json:"ProcMonitorMethod"` - Rules rulesOptions `json:"Rules"` Firewall string `json:"Firewall"` - FwOptions fwOptions `json:"FwOptions"` LogLevel *int32 `json:"LogLevel"` InterceptUnknown bool `json:"InterceptUnknown"` LogUTC bool `json:"LogUTC"` diff --git a/daemon/ui/config_utils.go b/daemon/ui/config_utils.go index 52564f8050..9dfc416300 100644 --- a/daemon/ui/config_utils.go +++ b/daemon/ui/config_utils.go @@ -115,7 +115,7 @@ func (c *Client) loadConfiguration(rawConfig []byte) bool { clientErrorRule.Duration = rule.Duration(clientConfig.DefaultDuration) } if clientConfig.ProcMonitorMethod != "" { - err := monitor.ReconfigureMonitorMethod(clientConfig.ProcMonitorMethod) + err := monitor.ReconfigureMonitorMethod(clientConfig.ProcMonitorMethod, clientConfig.Ebpf.ModulesPath) if err != nil { msg := fmt.Sprintf("Unable to set new process monitor (%s) method from disk: %v", clientConfig.ProcMonitorMethod, err.Msg) log.Warning(msg) diff --git a/daemon/ui/notifications.go b/daemon/ui/notifications.go index dd6199a041..4995185b0f 100644 --- a/daemon/ui/notifications.go +++ b/daemon/ui/notifications.go @@ -117,7 +117,10 @@ func (c *Client) handleActionChangeConfig(stream protocol.UI_NotificationsClient ) } - if err := monitor.ReconfigureMonitorMethod(newConf.ProcMonitorMethod); err != nil { + if err := monitor.ReconfigureMonitorMethod( + newConf.ProcMonitorMethod, + clientConfig.Ebpf.ModulesPath, + ); err != nil { c.sendNotificationReply(stream, notification.Id, "", err.Msg) return }