Sometimes we may receive a connection event after the exit of a
process:
[exec] /bin/xxx, pid 1234
[exit] /bin/xxx, pid 1234
[new conn] pid 1234 -> process unknown (on exec event and no /proc entry)
In these scenarios, we delay the deletion from cache a little
bit, to keep the PID available for a longer time.
When the Process Connector is used to intercept exec events, get and
build the process tree of a process.
PROCESS CONNECTOR feature was added here: 7a9bb17829
- Calculate the ram usage of a process in the daemon, using the page
size of the system.
- Added new functions to read some details of a process, so we can use
them in other parts of the code.
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..."
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
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.
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
- Fixed several leaks.
- Cache of events reorganized and improved.
* items are added faster.
* proc details are rebuilt if needed (checksums, proc tree, etc)
* proc's tree is reused if we've got the parent in cache.
rel: #413
Sometimes we receive /proc/self/exe as the path of the process (electron
apps).
Since a couple of systemd versions ago, some processes spawned by
systemd are reported as /proc/self/fd/<number>.
In these cases reading the symbolic link /proc/<pid>/exe points to the
file on disk.
- Obtain the process's parent hierarchy.
- Display the hierarchy on the pop-ups and the process dialog.
- [pop-ups] Added a Detailed view with all the metadata of the
process.
- [cache-events] Improved the cache of processes.
- [ruleseditor] Fixed enabling md5 checksum widget.
Related: #413, #406
Now you can create rules to filter processes by checksum. Only md5 is
available at the moment.
There's a global configuration option that you can use to enable or
disable this feature, from the config file or from the Preferences
dialog.
As part of this feature there have been more changes:
- New proc monitor method (PROCESS CONNECTOR) that listens for
exec/exit events from the kernel.
This feature depends on CONFIG_PROC_EVENTS kernel option.
- Only one cache of active processes for ebpf and proc monitor
methods.
More info and details: #413.
For the eBPF monitoring method, we listed and stored local addresses
every second, so that we could later check if the source IP of an
outbound connection was local or not, because sometimes we received
outbound connections like:
443:1.1.1.1 -> 192.168.1.123:12345
This could have been alread solved on this change e090833, so maybe
we no longer need this code.
- Now we subscribe to local addresses events, to receive add/remove
events asynchronously, without having to list local addrs
every second, alliviating CPU usage.
- Fixed creating context object to cancel subroutines. It was not
working properly when switching between proc monitor methods.
When using proc monitor method + interceptUnknown, allow to ask the user
about connections not associated with a process. Usually they're safe to
discard, but on some special cases it helps not disrupt some services.
Block of code to find connections via netstat moved to procmon/
- Fixed firewall dialog label alignment.
- Fixed potential race condition when stopping the daemon, and there're
connections being enqueued.
- Added "clear" button to GUI's filter line (#786)
- Create ebpf cache object only if the modules have been loaded.
- Set default stats workers to the sme amount defined in configuration.
Closes#785
Under certain situations, like when using systemd-resolved as DNS
resolver, we receive outbound connections with the fields swapped:
Instead of: local-port:local-ip -> public-ip:public-port
we receive: public-port:public-ip -> local-ip:local-port
Sometimes this behaviour causes network slowdowns, or no network at all.
If we swap the fields of these connections, then we're able to get the
process and keep functioning as usual. But what causes this behaviour is
yet unknown, and needs further analysis.
See these issues for more information: #779 , #711
In order to detect short-lived processes we intercept new processes
executions as they happen, and cache them for later use.
When a new connection is established, then we check if the PID of the
connection is cached, and use the details of the process to ask the user
to allow or deny it.
However, there're some situations where the path or cmdline of a PID,
doesn't correspond with the one that's establishing the connection.
Given the same PID:
- Sometimes we receive from the tracepoint a wrong/non-existent path.
- Other times we receive a "helper" which is the one executing the
real binary that opens the connection.
For these reasons now when a new connection is established, we read the
path to the binary from proc. If the PID is cached and the cached path
differs, then we'll use the path from proc.
We lose a bit of performance, but hopefully we'll be more consistent
with what the user expect, while at the same time keeping intercepting
short-lived processes.
Downsides: for execveat() executions we won't display the original binary.
Closes#771