Added new task to monitor the resources of remote nodes, like
ram, swap, number of processes or load average of the system.
The task is initiated when the user selects a node, and the data
received from the node is added to the right panel of the Nodes tab.
The task is stopped when changing to another tab, or when deselecting a
node.
Particularly useful for monitoring remote nodes.
daemon tasks are actions that are executed in background by the daemon.
They're started from the GUI (server) via a Notification (protobuf),
with the type TASK_START (protobuf).
Once received in the daemon, the TaskManager starts the task in
background.
Tasks may run at interval times (every 5s, 2days, etc), until they
finish an operation, until a timeout, etc.
Each task has each own configuration options, which will customize the
behaviour of its operations.
In this version, if the GUI is closed, the daemon will stop all the
running tasks.
Each Task has a flag to ignore this behaviour, for example if they need
to run until they finish and only send a notification to the GUI,
instead of streaming data continuously to the GUI (server).
- Up until now we only had one task that could be initiated from the GUI:
the process monitor dialog. It has been migrated to a Task{}.
- go.mod bumped to v1.20, to use unsafe string functions.
- go.sum updated accordingly.
When exporting rules from the GUI, the Created field was exported as
timestamp. Importing rules worked fine, because json.Marshall() accepts
the timestamp format.
However, when the daemon was loading a rule with the Created field as
timestamp, since the field was defined as time.Time, it expected a RFC3339
string (https://pkg.go.dev/time#Time.UnmarshalJSON)
so it failed to parse the timestamp and the rule was not loaded.
Now the field is defined as string, it's always saved as RFC3339, and if
we fail to parse these fields we'll use a temporary date instead of
failing loading the rule.
More info:
https://github.com/evilsocket/opensnitch/issues/1140#issuecomment-2140904847Closes#1140
Start monitoring the config file every time we read the file, to survive:
- malformed json file
- intermediate file removal (when writing we receive 2 write events,
one of0 bytes)
"A watch will be automatically removed if the watched path is deleted or
renamed"
"A path can only be watched once; watching it more than once is a no-op and
will not return an error"
https://pkg.go.dev/github.com/fsnotify/fsnotify#Watcher.Add
- When reloading rules from a path:
stop existing (domains,ips,regexp) lists monitors, stop rules
watcher and start watching the new dir for changes, delete existing
rules from memory, etc.
- Previously, cli parameters (queue number, log file, etc) were taking
into account before loading the configuration.
Now the configuration file is loaded first (default-config.json), and
if any of the cli parameter has been specified, it'll overwrite the
loaded configuration from file.
This means for example that if you use "-process-monitor-method proc",
and "ebpf" is configured in default-config.json, firstly "ebpf" will
be configured, and later "proc".
(-queue-num option for now requires to match config option
cfg.FwOptions.QueueNumber)
Allow to customize:
- EventsWorkers: number of goroutines to handle kernel events.
Default 8.
- QueueEventsSize: max number of events in the queue.
By default 0, meaning that it'll relay on the available goroutines to
process the events. If it's > 0, and the daemon can't process the
events fast enough, they'll be queued. Once the queue is full, it'll
behave as it was of size 0.
If there're lost events, a message will be logged: "Lost ebpf events..."
- 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
- The loggers were not being properly initialized.
- The fw was only being load on reload, instead of on startup
and reload.
Kudos to @1fishe2fishe for reporting this problem and proposing a
fix in #1130!
By default when adding the interception rules, we were killing all
existing connections, to force them go to the netfilter queue.
However in some environments this is not acceptable, so now it's configurable.
Besides, we were doing this only for nftables, so now it also works for
iptables.
When disabling the interception from the server (GUI), the network
interception was stopped, but the procs monitor kept running.
Now the procs monitor in use is also stopped, not to interfere with
the rest of the system (except 'proc').
improvements to the loggers modules:
- allow to specify a connection timeout (there was only a write
timeout).
- performance improvements when building the messages to be
written/sent.
- allow to restart the connection with remote servers if we fill up the
messages queue.
This can occur for example if we connect to a remote server, start
sending messages, but we haven't allowed other connections yet.
In this case the connections never recovered from this state, and we
weren't prompted to allow the needed connections.
(more work nd testing needed)
continuation of previous commit bde5d34deb
- Allow to reconfigure stats limits (how many events we keep on the
daemon, number of workers, ...)
- Allow to reconfigure loggers.
We only offered two options for the DefaultAction option: allow/deny.
Since a long time ago we support "reject"ing connections, but it was not
configurable as the DefaultAction.
Closes: #1108
We build the parent process tree of a process when it's executed
for the first time.
Now we also build the tree when an already running process opens a new
outbound connection by the first time.
if an invalid opensnitch-procs.o module was loaded, we were flooding
the log with errors.
In these cases stop processing events after 20 errors (random, we should
have no errors).
This may occur if the module is malformed (valid .o ebpf module but
different structs, etc), or when loading modules from other versions.
Closes: #1099#1082
We were not reacting to common exit signals, only to kill/interrupt
signals, so the DNS uprobes were never properly removed. Each uprobe
has the PID of the daemon in the identifier, so in theory, there
shouldn't be conflicts, but better clean our probes on exit.
previous to this commit with the daemon running
(and lot of starts/stops):
~ # cat /sys/kernel/debug/tracing/uprobe_events |wc -l
367
after stopping the daemon:
~ # cat /sys/kernel/debug/tracing/uprobe_events |wc -l
364
~ # > /sys/kernel/debug/tracing/uprobe_events
~ # cat /sys/kernel/debug/tracing/uprobe_events |wc -l
0
~ # cp opensnitchd-new /usr/bin/opensnitchd ; service opensnitchd start
~ # cat /sys/kernel/debug/tracing/uprobe_events |wc -l
3
~ # service opensnitchd stop
~ # cat /sys/kernel/debug/tracing/uprobe_events |wc -l
0
Added the path to the libc as well as the calculated offset for the
uprobe.
Don't return on the first error found loading a uprobe, instead try all
the uprobes and return if the loaded uprobes are 0.
There's a long running task that monitors established connections every
~2s.
When a connection is not found via ebpf or proc, sometimes it's found
there so we can use the inode to search for the process.
However on some systems the netlink call to dump the sockets may fail
continuously, wasting resources. It'll also fail if you block connections
to port 0 (common case for ICMP packets).
So if there're too many errors dumpng the sockets, stop this task for
these cases.
- When discovering the hierarchy of a process, reuse components of
the tree if they're already on cache, to improve speed and reduce
mem allocs.
- When building the tree of a proces, rebuild the tree if the first
component doesn't have pid 1. Otherwise reuse the tree.
Simplify the cache of connections by storing only the PID of a process,
instead of the Process object.
We can obtain the Process object from the cache of processes by PID.
Added config option to set how often the garbage collector runs.
For example:
"Internal": {
"GCPercent": 75
},
If this option is not specified in the config file, or the value
is 0, then the GC percentage is not configured.
More info:
https://pkg.go.dev/runtime/debug#SetGCPercent
By default load the system fw config file from
/etc/opensnitchd/system-fw.json.
There're these options to specify the file to load:
- via cli option with -fw-config-file
- writing it in the default-config.json file:
"FwOptions": { "ConfigPath": "..." }
If both options are empty, then the default one is used.
FIXME:
When the cli option is used to load the fw configuration, and the main
preferences are saved, the fw is reloaded but the path to the fw config
is lost.
On this test we assumed that there would always be reading stats for our
own process /proc/self, but on restricted environments that might not
alwys be the case. Anyway, a value of 0 is not an error in itself.
Closes#1075
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