Summary:
The systemd service unit can be enhanced to start BEFORE any network is configured, and thus allow interception and protection at an earlier stage...
Service file:
Below is my crafted service file:
# /etc/systemd/system/opensnitchd.service
[Unit]
Description=Application firewall OpenSnitch
Documentation=https://github.com/gustavo-iniguez-goya/opensnitch/wiki
Documentation=man:systemd.special
Documentation=man:systemd.service
Documentation=man:systemd.exec
Documentation=man:systemd.unit
DefaultDependencies=no
Before=network-pre.target shutdown.target
Wants=network-pre.target
Conflicts=shutdown.target
# Don't start when 'no-appfw` is in kernel command-line, to allow booting without it.
ConditionKernelCommandLine=!no-appfw
[Service]
Type=exec
ConfigurationDirectory=%N/rules
ConfigurationDirectoryMode=0700
Environment='custom_cfg=%E/%N/rules'
# Environment='opts=-debug'
ExecCondition=%N -check-requirements
ExecStart=%N -rules-path $custom_cfg $opts
# Signal-info was taken from the init.d script, but it just exits and then systemd restarts the service...
ExecReload=kill -HUP $MAINPID
Restart=always
RestartSec=30
TimeoutStopSec=10
# Ensure it is not killed by the Linux kernel's Out-Of-Memory (OOM) killer.
# https://www.freedesktop.org/software/systemd/man/systemd.exec.html#OOMScoreAdjust=
OOMScoreAdjust=-1000
[Install]
WantedBy=basic.target
Notable changes/additions:
-
Unit filename:
⚠️ The service filename was changed to opensnitchd.service !!!
This was needed for automatically using the unit name in the service definition using the %N specifier...
See: Specifiers@man systemd.unit#Specifiers
- The previous filename was lacking the
d in it's name !
- Thus if you want to use this service file while at same time having the currently distributed unit file in your system you need to "mask" the old one to prevent it from being used and started:
sudo systemctl mask --now opensnitch.service
-
Unit ordering:
Made sure the daemon starts before any network related devices or services are created/started by using network-pre.target, See:
-
Startup target / run-level:
Changed the default install target to basic.target instead of multi-user.target.
This will allow it to run in any "run-level" in SysV terms.
See: Units managed by the system service manager@man systemd.special#basic.target
-
Automatically disable using a kernel-command-line option:
Just in case it is needed, i added the ability to disable the daemon using a kernel-command-line option using the ConditionKernelCommandLine directive.
When the no-appfw option is present in the kernel-command-line, the daemon will not startup.
This option functions same as the well-known quite option. (only applies when present as a separate word)
-
Automatically create rules directory:
Let systemd automatically create the "rules" directory with proper mode, when non-existent yet, upon starting the daemon service by using the ConfigurationDirectory and ConfigurationDirectoryMode directives.
-
Automatically check for kernel support before starting:
Automatically prevent startup when required kernel support is not present by using the -check-requirements flag in a ExecCondition directive.
(This assumes the command returns a non-zero exit status when not satisfied.)
-
Reload functionality:
Added support for reloading the daemon using the ExecReload directive.
Signal-info was taken from the init.d script, but it just exits and then systemd restarts the service...
So this functionality either needs to be implemented in the daemon's code or a different signal needs to be sent to it.
But at least the functionality is now present in the unit file.
-
Prevent from being killed by the OOM-Killer:
Prevented the daemon to be killed by the Linux kernel's Out-Of-Memory (OOM) killer, using the OOMScoreAdjust=-1000 directive.
See: OOMScoreAdjust@man systemd.exec#OOMScoreAdjust
(This will ensure that the protection keeps functioning even when other processes cause an OOM)
-
Admin overrides using drop-ins:
Added support for easily adjusting the directory used for rules and extra options by the local admin.
The local admin can create "drop-in" config(s) under /etc/systemd/system/opensnitchd.service.d/ even when the service file is installed in other places by the package maintainer, See: 16.14. Extending the default unit configuration@redhat.com
Example drop-in(s) contents that can-be-used:
One last thing to improve systemd usage:
Please add a way to prevent timestamps being output at all, when using /dev/stdout as log destination.
Or at least add a syslog option to use as logger, which also doesn't need timestamps because it adds them self.
Look how ugly it is at moment:
$ systemctl status opensnitchd
● opensnitchd.service - Application firewall OpenSnitch
Loaded: loaded (/etc/systemd/system/opensnitchd.service; enabled; preset: enabled)
Active: active (running) since Tue 2023-08-15 16:09:57 +03; 1h 47min ago
Docs: https://github.com/gustavo-iniguez-goya/opensnitch/wiki
man:systemd.special
man:systemd.service
man:systemd.exec
man:systemd.unit
Process: 593 ExecCondition=opensnitchd -check-requirements (code=exited, status=0/SUCCESS)
Main PID: 632 (opensnitchd)
Tasks: 26 (limit: 38131)
Memory: 81.4M
CPU: 1min 42.501s
CGroup: /system.slice/opensnitchd.service
└─632 opensnitchd -rules-path /etc/opensnitchd/rules
Aug 15 16:09:57 kubuntu opensnitchd[632]: [2023-08-15 13:09:57] IMP Starting opensnitch-daemon v1.6.1
Aug 15 16:09:57 kubuntu opensnitchd[632]: [2023-08-15 13:09:57] INF Loading rules from /etc/opensnitchd/rules ...
Aug 15 16:09:57 kubuntu opensnitchd[632]: [2023-08-15 13:09:57] INF loading domains lists: lists, lists.domains_regexp, /mnt/LutrisGames/OpenSnitch-Firewall-Lists/WoT-Blitz-allow
Aug 15 16:09:57 kubuntu opensnitchd[632]: [2023-08-15 13:09:57] INF monitor lists started: /mnt/LutrisGames/OpenSnitch-Firewall-Lists/WoT-Blitz-allow
Aug 15 16:09:57 kubuntu opensnitchd[632]: [2023-08-15 13:09:57] INF loading domains lists: lists, lists.domains_regexp, /mnt/LutrisGames/OpenSnitch-Firewall-Lists/WoT-Blitz-reject
Aug 15 16:09:57 kubuntu opensnitchd[632]: [2023-08-15 13:09:57] INF monitor lists started: /mnt/LutrisGames/OpenSnitch-Firewall-Lists/WoT-Blitz-reject
Aug 15 16:09:57 kubuntu opensnitchd[632]: [2023-08-15 16:09:57] INF [eBPF] module loaded: /usr/lib/opensnitchd/ebpf/opensnitch.o
Aug 15 16:09:57 kubuntu opensnitchd[632]: [2023-08-15 16:09:57] INF [eBPF] module loaded: /usr/lib/opensnitchd/ebpf/opensnitch-procs.o
Aug 15 16:09:57 kubuntu opensnitchd[632]: [2023-08-15 16:09:57] INF Process monitor method ebpf
Aug 15 16:09:57 kubuntu opensnitchd[632]: [2023-08-15 16:09:57] INF Stats, max events: 25, max stats: 150, max workers: 6
Aug 15 16:09:57 kubuntu opensnitchd[632]: [2023-08-15 16:09:57] INF nftables config changed, reloading
Aug 15 16:09:57 kubuntu opensnitchd[632]: [2023-08-15 16:09:57] INF fw configuration loaded
Aug 15 16:09:58 kubuntu opensnitchd[632]: [2023-08-15 16:09:58] INF Using nftables firewall
Aug 15 16:09:58 kubuntu opensnitchd[632]: [2023-08-15 16:09:58] INF Running on netfilter queue #0 ...
Aug 15 16:09:58 kubuntu opensnitchd[632]: [2023-08-15 16:09:58] INF [eBPF] module loaded: /usr/lib/opensnitchd/ebpf/opensnitch-dns.o
Aug 15 16:09:58 kubuntu opensnitchd[632]: found /lib/x86_64-linux-gnu/libc.so.6
Aug 15 16:10:03 kubuntu opensnitchd[632]: [2023-08-15 16:10:03] INF clearing domains lists: 0 - /mnt/LutrisGames/OpenSnitch-Firewall-Lists/WoT-Blitz-reject
Aug 15 16:10:03 kubuntu opensnitchd[632]: [2023-08-15 16:10:03] INF clearing domains lists: 0 - /mnt/LutrisGames/OpenSnitch-Firewall-Lists/WoT-Blitz-allow
Aug 15 16:10:03 kubuntu opensnitchd[632]: [2023-08-15 16:10:03] INF 6 regexps loaded, /mnt/LutrisGames/OpenSnitch-Firewall-Lists/WoT-Blitz-reject/re.txt
Aug 15 16:10:03 kubuntu opensnitchd[632]: [2023-08-15 16:10:03] INF 1 lists loaded, 6 domains, 0 duplicated
Aug 15 16:10:03 kubuntu opensnitchd[632]: [2023-08-15 16:10:03] INF 19 regexps loaded, /mnt/LutrisGames/OpenSnitch-Firewall-Lists/WoT-Blitz-allow/re.txt
Aug 15 16:10:03 kubuntu opensnitchd[632]: [2023-08-15 16:10:03] INF 1 lists loaded, 19 domains, 0 duplicated
Aug 15 16:10:35 kubuntu opensnitchd[632]: [2023-08-15 16:10:35] INF Connected to the UI service on ///tmp/osui.sock
Aug 15 16:10:35 kubuntu opensnitchd[632]: [2023-08-15 16:10:35] IMP UI connected, dispathing queued alerts: 0
Aug 15 16:10:35 kubuntu opensnitchd[632]: [2023-08-15 16:10:35] INF Start receiving notifications
Summary:
The systemd service unit can be enhanced to start BEFORE any network is configured, and thus allow interception and protection at an earlier stage...
Service file:
Below is my crafted service file:
Notable changes/additions:
Unit filename:
⚠️ The service filename was changed to
opensnitchd.service!!!This was needed for automatically using the unit name in the service definition using the
%Nspecifier...See: Specifiers@man
systemd.unit#Specifiersdin it's name !Unit ordering:
Made sure the daemon starts before any network related devices or services are created/started by using
network-pre.target, See:Startup target / run-level:
Changed the default install target to
basic.targetinstead ofmulti-user.target.This will allow it to run in any "run-level" in SysV terms.
See: Units managed by the system service manager@man
systemd.special#basic.targetAutomatically disable using a kernel-command-line option:
Just in case it is needed, i added the ability to disable the daemon using a kernel-command-line option using the
ConditionKernelCommandLinedirective.When the
no-appfwoption is present in the kernel-command-line, the daemon will not startup.This option functions same as the well-known
quiteoption. (only applies when present as a separate word)Automatically create rules directory:
Let systemd automatically create the "rules" directory with proper mode, when non-existent yet, upon starting the daemon service by using the
ConfigurationDirectoryandConfigurationDirectoryModedirectives.Automatically check for kernel support before starting:
Automatically prevent startup when required kernel support is not present by using the
-check-requirementsflag in aExecConditiondirective.(This assumes the command returns a non-zero exit status when not satisfied.)
Reload functionality:
Added support for reloading the daemon using the
ExecReloaddirective.Signal-info was taken from the init.d script, but it just exits and then systemd restarts the service...
So this functionality either needs to be implemented in the daemon's code or a different signal needs to be sent to it.
But at least the functionality is now present in the unit file.
Prevent from being killed by the OOM-Killer:
Prevented the daemon to be killed by the Linux kernel's Out-Of-Memory (OOM) killer, using the
OOMScoreAdjust=-1000directive.See: OOMScoreAdjust@man
systemd.exec#OOMScoreAdjust(This will ensure that the protection keeps functioning even when other processes cause an OOM)
Admin overrides using drop-ins:
Added support for easily adjusting the directory used for rules and extra options by the local admin.
The local admin can create "drop-in" config(s) under
/etc/systemd/system/opensnitchd.service.d/even when the service file is installed in other places by the package maintainer, See: 16.14. Extending the default unit configuration@redhat.comExample drop-in(s) contents that can-be-used:
To change the rules directory to be used:
$custom_cfgis supplied as an argument to the-rules-pathoption of the daemon.systemd.unit#Specifiers%Eexpands to/etc%Nexpands to the unit nameopensnitchd/etc/opensnitchd/rules-specialTo enable debug output:
$optsis supplied as extra argument(s) to the daemon.Combination of both:
One last thing to improve systemd usage:
Please add a way to prevent timestamps being output at all, when using
/dev/stdoutas log destination.Or at least add a
syslogoption to use as logger, which also doesn't need timestamps because it adds them self.Look how ugly it is at moment: