Skip to content

Commit ffb7668

Browse files
allow to configure ebpf modules path
Now it's possible to configure eBPF modules path from the default-config.json file: "Ebpf": { "ModulesPath": "..." } If the option is not provided, or if it's empty, we'll keep loading from the default directories: - /usr/local/lib/opensnitchd/ebpf - /usr/lib/opensnitchd/ebpf - /etc/opensnitchd/ebpf (deprecated, will be removed in the future). Closes #928
1 parent 090bb0e commit ffb7668

File tree

10 files changed

+85
-63
lines changed

10 files changed

+85
-63
lines changed

daemon/core/ebpf.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ import (
77
"github.com/iovisor/gobpf/elf"
88
)
99

10-
// LoadEbpfModule loads the given eBPF module
11-
// It'll try to load from several paths.
12-
func LoadEbpfModule(module string) (m *elf.Module, err error) {
10+
// LoadEbpfModule loads the given eBPF module, from the given path if specified.
11+
// Otherwise t'll try to load the module from several default paths.
12+
func LoadEbpfModule(module, path string) (m *elf.Module, err error) {
1313
var (
1414
modulesDir = "/opensnitchd/ebpf"
1515
paths = []string{
@@ -18,6 +18,12 @@ func LoadEbpfModule(module string) (m *elf.Module, err error) {
1818
fmt.Sprint("/etc/opensnitchd"), // Deprecated: will be removed in future versions.
1919
}
2020
)
21+
22+
// if path has been specified, try to load the module from there.
23+
if path != "" {
24+
paths = []string{path}
25+
}
26+
2127
modulePath := ""
2228
moduleError := fmt.Errorf(`Module not found (%s) in any of the paths.
2329
You may need to install the corresponding package`, module)

daemon/dns/ebpfhook.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,8 @@ func lookupSymbol(elffile *elf.File, symbolName string) (uint64, error) {
9393
}
9494

9595
// ListenerEbpf starts listening for DNS events.
96-
func ListenerEbpf() error {
97-
m, err := core.LoadEbpfModule("opensnitch-dns.o")
96+
func ListenerEbpf(ebpfModPath string) error {
97+
m, err := core.LoadEbpfModule("opensnitch-dns.o", ebpfModPath)
9898
if err != nil {
9999
log.Error("[eBPF DNS]: %s", err)
100100
return err

daemon/firewall/common/common.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ func (c *Common) NewRulesChecker(areRulesLoaded callbackBool, reloadRules callba
138138
}
139139
}
140140
c.stopChecker = make(chan bool, 1)
141-
log.Info("Starting new fw checker every %s ...", DefaultCheckInterval)
141+
log.Info("Starting new fw checker every %s ...", c.RulesCheckInterval)
142142
c.RulesChecker = time.NewTicker(c.RulesCheckInterval)
143143

144144
go startCheckingRules(c.stopChecker, c.RulesChecker, areRulesLoaded, reloadRules)

daemon/main.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ var (
6464
rulesPath = "/etc/opensnitchd/rules/"
6565
configFile = "/etc/opensnitchd/default-config.json"
6666
fwConfigFile = "/etc/opensnitchd/system-fw.json"
67+
ebpfModPath = "" // /usr/lib/opensnitchd/ebpf
6768
noLiveReload = false
6869
queueNum = 0
6970
repeatQueueNum int //will be set later to queueNum + 1
@@ -100,13 +101,14 @@ func init() {
100101

101102
flag.StringVar(&procmonMethod, "process-monitor-method", procmonMethod, "How to search for processes path. Options: ftrace, audit (experimental), ebpf (experimental), proc (default)")
102103
flag.StringVar(&uiSocket, "ui-socket", uiSocket, "Path the UI gRPC service listener (https://github.com/grpc/grpc/blob/master/doc/naming.md).")
103-
flag.StringVar(&rulesPath, "rules-path", rulesPath, "Path to load JSON rules from.")
104104
flag.IntVar(&queueNum, "queue-num", queueNum, "Netfilter queue number.")
105105
flag.IntVar(&workers, "workers", workers, "Number of concurrent workers.")
106106
flag.BoolVar(&noLiveReload, "no-live-reload", debug, "Disable rules live reloading.")
107107

108+
flag.StringVar(&rulesPath, "rules-path", rulesPath, "Path to load JSON rules from.")
108109
flag.StringVar(&configFile, "config-file", configFile, "Path to the daemon configuration file.")
109110
flag.StringVar(&fwConfigFile, "fw-config-file", fwConfigFile, "Path to the system fw configuration file.")
111+
//flag.StringVar(&ebpfModPath, "ebpf-modules-path", ebpfModPath, "Path to the directory with the eBPF modules.")
110112
flag.StringVar(&logFile, "log-file", logFile, "Write logs to this file instead of the standard output.")
111113
flag.BoolVar(&logUTC, "log-utc", logUTC, "Write logs output with UTC timezone (enabled by default).")
112114
flag.BoolVar(&logMicro, "log-micro", logMicro, "Write logs output with microsecond timestamp (disabled by default).")
@@ -582,15 +584,15 @@ func main() {
582584
// overwrite monitor method from configuration if the user has passed
583585
// the option via command line.
584586
if procmonMethod != "" {
585-
if err := monitor.ReconfigureMonitorMethod(procmonMethod); err != nil {
587+
if err := monitor.ReconfigureMonitorMethod(procmonMethod, cfg.Ebpf.ModulesPath); err != nil {
586588
msg := fmt.Sprintf("Unable to set process monitor method via parameter: %v", err)
587589
uiClient.SendWarningAlert(msg)
588590
log.Warning(msg)
589591
}
590592
}
591593

592-
go func(uiClient *ui.Client) {
593-
if err := dns.ListenerEbpf(); err != nil {
594+
go func(uiClient *ui.Client, ebpfPath string) {
595+
if err := dns.ListenerEbpf(ebpfPath); err != nil {
594596
msg := fmt.Sprintf("EBPF-DNS: Unable to attach ebpf listener: %s", err)
595597
log.Warning(msg)
596598
// don't display an alert, since this module is not critical
@@ -602,7 +604,7 @@ func main() {
602604
msg)
603605

604606
}
605-
}(uiClient)
607+
}(uiClient, ebpfModPath)
606608

607609
initSystemdResolvedMonitor()
608610

daemon/procmon/ebpf/ebpf.go

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,12 @@ type Error struct {
5252
}
5353

5454
var (
55-
m, perfMod *elf.Module
56-
lock = sync.RWMutex{}
57-
mapSize = uint(12000)
58-
ebpfMaps map[string]*ebpfMapsForProto
55+
m, perfMod *elf.Module
56+
lock = sync.RWMutex{}
57+
mapSize = uint(12000)
58+
ebpfMaps map[string]*ebpfMapsForProto
59+
modulesPath string
60+
5961
//connections which were established at the time when opensnitch started
6062
alreadyEstablished = alreadyEstablishedConns{
6163
TCP: make(map[*daemonNetlink.Socket]int),
@@ -75,7 +77,9 @@ var (
7577
)
7678

7779
//Start installs ebpf kprobes
78-
func Start() *Error {
80+
func Start(modPath string) *Error {
81+
modulesPath = modPath
82+
7983
setRunning(false)
8084
if err := mountDebugFS(); err != nil {
8185
return &Error{
@@ -84,7 +88,7 @@ func Start() *Error {
8488
}
8589
}
8690
var err error
87-
m, err = core.LoadEbpfModule("opensnitch.o")
91+
m, err = core.LoadEbpfModule("opensnitch.o", modulesPath)
8892
if err != nil {
8993
dispatchErrorEvent(fmt.Sprint("[eBPF]: ", err.Error()))
9094
return &Error{NotAvailable, fmt.Errorf("[eBPF] Error loading opensnitch.o: %s", err.Error())}

daemon/procmon/ebpf/events.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ func initEventsStreamer() *Error {
7575
elfOpts := make(map[string]elf.SectionParams)
7676
elfOpts["maps/"+perfMapName] = elf.SectionParams{PerfRingBufferPageCount: ringBuffSize}
7777
var err error
78-
perfMod, err = core.LoadEbpfModule("opensnitch-procs.o")
78+
perfMod, err = core.LoadEbpfModule("opensnitch-procs.o", modulesPath)
7979
if err != nil {
8080
dispatchErrorEvent(fmt.Sprint("[eBPF events]: ", err))
8181
return &Error{EventsNotAvailable, err}

daemon/procmon/monitor/init.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ func stopProcMonitors() {
5050
}
5151

5252
// ReconfigureMonitorMethod configures a new method for parsing connections.
53-
func ReconfigureMonitorMethod(newMonitorMethod string) *Error {
53+
func ReconfigureMonitorMethod(newMonitorMethod, ebpfModulesPath string) *Error {
5454
if procmon.GetMonitorMethod() == newMonitorMethod {
5555
return nil
5656
}
@@ -64,7 +64,7 @@ func ReconfigureMonitorMethod(newMonitorMethod string) *Error {
6464
// if the new monitor method fails to start, rollback the change and exit
6565
// without saving the configuration. Otherwise we can end up with the wrong
6666
// monitor method configured and saved to file.
67-
err := Init()
67+
err := Init(ebpfModulesPath)
6868
if err.What > NoError {
6969
log.Error("Reconf() -> Init() error: %v", err)
7070
procmon.SetMonitorMethod(oldMethod)
@@ -85,7 +85,7 @@ func End() {
8585
}
8686

8787
// Init starts parsing connections using the method specified.
88-
func Init() (errm *Error) {
88+
func Init(ebpfModulesPath string) (errm *Error) {
8989
errm = &Error{}
9090

9191
if cacheMonitorsRunning == false {
@@ -94,7 +94,7 @@ func Init() (errm *Error) {
9494
}
9595

9696
if procmon.MethodIsEbpf() {
97-
err := ebpf.Start()
97+
err := ebpf.Start(ebpfModulesPath)
9898
if err == nil {
9999
log.Info("Process monitor method ebpf")
100100
return errm

daemon/ui/config/config.go

Lines changed: 46 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -13,60 +13,67 @@ import (
1313
"github.com/evilsocket/opensnitch/daemon/statistics"
1414
)
1515

16-
type serverTLSOptions struct {
17-
CACert string `json:"CACert"`
18-
ServerCert string `json:"ServerCert"`
19-
ServerKey string `json:"ServerKey"`
20-
ClientCert string `json:"ClientCert"`
21-
ClientKey string `json:"ClientKey"`
22-
// https://pkg.go.dev/crypto/tls#Config
23-
SkipVerify bool `json:"SkipVerify"`
24-
//https://pkg.go.dev/crypto/tls#ClientAuthType
25-
ClientAuthType string `json:"ClientAuthType"`
16+
type (
17+
serverTLSOptions struct {
18+
CACert string `json:"CACert"`
19+
ServerCert string `json:"ServerCert"`
20+
ServerKey string `json:"ServerKey"`
21+
ClientCert string `json:"ClientCert"`
22+
ClientKey string `json:"ClientKey"`
23+
// https://pkg.go.dev/crypto/tls#Config
24+
SkipVerify bool `json:"SkipVerify"`
25+
// https://pkg.go.dev/crypto/tls#ClientAuthType
26+
ClientAuthType string `json:"ClientAuthType"`
2627

27-
// https://pkg.go.dev/crypto/tls#Conn.VerifyHostname
28-
//VerifyHostname bool
29-
// https://pkg.go.dev/crypto/tls#example-Config-VerifyConnection
30-
// VerifyConnection bool
31-
// VerifyPeerCertificate bool
32-
}
28+
// https://pkg.go.dev/crypto/tls#Conn.VerifyHostname
29+
// VerifyHostname bool
30+
// https://pkg.go.dev/crypto/tls#example-Config-VerifyConnection
31+
// VerifyConnection bool
32+
// VerifyPeerCertificate bool
33+
}
3334

34-
type serverAuth struct {
35-
// token?, google?, simple-tls, mutual-tls
36-
Type string `json:"Type"`
37-
TLSOptions serverTLSOptions `json:"TLSOptions"`
38-
}
35+
serverAuth struct {
36+
// token?, google?, simple-tls, mutual-tls
37+
Type string `json:"Type"`
38+
TLSOptions serverTLSOptions `json:"TLSOptions"`
39+
}
3940

40-
type serverConfig struct {
41-
Address string `json:"Address"`
42-
Authentication serverAuth `json:"Authentication"`
43-
LogFile string `json:"LogFile"`
44-
Loggers []loggers.LoggerConfig `json:"Loggers"`
45-
}
41+
serverConfig struct {
42+
Address string `json:"Address"`
43+
Authentication serverAuth `json:"Authentication"`
44+
LogFile string `json:"LogFile"`
45+
Loggers []loggers.LoggerConfig `json:"Loggers"`
46+
}
4647

47-
type rulesOptions struct {
48-
Path string `json:"Path"`
49-
EnableChecksums bool `json:"EnableChecksums"`
50-
}
48+
rulesOptions struct {
49+
Path string `json:"Path"`
50+
EnableChecksums bool `json:"EnableChecksums"`
51+
}
5152

52-
type fwOptions struct {
53-
Firewall string `json:"Firewall"`
54-
ConfigPath string `json:"ConfigPath"`
55-
ActionOnOverflow string `json:"ActionOnOverflow"`
56-
MonitorInterval string `json:"MonitorInterval"`
57-
}
53+
fwOptions struct {
54+
Firewall string `json:"Firewall"`
55+
ConfigPath string `json:"ConfigPath"`
56+
BypassQueue string `json:"BypassQueue"`
57+
MonitorInterval string `json:"MonitorInterval"`
58+
}
59+
60+
ebpfOptions struct {
61+
ModulesPath string `json:"ModulesPath"`
62+
}
63+
)
5864

5965
// Config holds the values loaded from configFile
6066
type Config struct {
6167
sync.RWMutex
6268
Server serverConfig `json:"Server"`
6369
Stats statistics.StatsConfig `json:"Stats"`
70+
Rules rulesOptions `json:"Rules"`
71+
Ebpf ebpfOptions `json:"Ebpf"`
72+
FwOptions fwOptions `json:"FwOptions"`
6473
DefaultAction string `json:"DefaultAction"`
6574
DefaultDuration string `json:"DefaultDuration"`
6675
ProcMonitorMethod string `json:"ProcMonitorMethod"`
67-
Rules rulesOptions `json:"Rules"`
6876
Firewall string `json:"Firewall"`
69-
FwOptions fwOptions `json:"FwOptions"`
7077
LogLevel *int32 `json:"LogLevel"`
7178
InterceptUnknown bool `json:"InterceptUnknown"`
7279
LogUTC bool `json:"LogUTC"`

daemon/ui/config_utils.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ func (c *Client) loadConfiguration(rawConfig []byte) bool {
115115
clientErrorRule.Duration = rule.Duration(clientConfig.DefaultDuration)
116116
}
117117
if clientConfig.ProcMonitorMethod != "" {
118-
err := monitor.ReconfigureMonitorMethod(clientConfig.ProcMonitorMethod)
118+
err := monitor.ReconfigureMonitorMethod(clientConfig.ProcMonitorMethod, clientConfig.Ebpf.ModulesPath)
119119
if err != nil {
120120
msg := fmt.Sprintf("Unable to set new process monitor (%s) method from disk: %v", clientConfig.ProcMonitorMethod, err.Msg)
121121
log.Warning(msg)

daemon/ui/notifications.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,10 @@ func (c *Client) handleActionChangeConfig(stream protocol.UI_NotificationsClient
117117
)
118118
}
119119

120-
if err := monitor.ReconfigureMonitorMethod(newConf.ProcMonitorMethod); err != nil {
120+
if err := monitor.ReconfigureMonitorMethod(
121+
newConf.ProcMonitorMethod,
122+
clientConfig.Ebpf.ModulesPath,
123+
); err != nil {
121124
c.sendNotificationReply(stream, notification.Id, "", err.Msg)
122125
return
123126
}

0 commit comments

Comments
 (0)