The current version of the systemd unit for zerotier-one linux agent is “unsafe” at least based on the systemd default analyser do think so:
systemd-analyze security zerotier-one.service
…
Overall exposure level for zerotier-one.service: 9.6 UNSAFE
Kind of good example is usbguard usbguard/usbguard.service.in at 5505735ad83fbbed79504aaa4297baf4ce791642 · USBGuard/usbguard · GitHub
Loci
July 12, 2022, 7:40am
2
Here’s mine
[Service]
### no-hang
TimeoutStopSec=5
###Sandboxing
NoNewPrivileges=yes
PrivateTmp=yes
ProtectHome=yes
ProtectControlGroups=yes
ProtectKernelModules=yes
ProtectKernelTunables=yes
ProtectKernelLogs=yes
ProtectHostname=yes
ProtectUsers=yes
CapabilityBoundingSet=CAP_NET_ADMIN
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6 AF_NETLINK
RestrictNamespaces=yes
RestrictRealtime=yes
RestrictSUIDSGID=yes
LockPersonality=yes
SystemCallArchitectures=native
SystemCallFilter=@system-service @network-io
UMask=0077
Seems to work fine. Gives 4.0 OK
score
You could lock it down further with DeviceAllow=
and a more tuned CapabilityBoundingSet=
among other things.
1 Like
I tried it out before sending a PR but for me this above does not work:
fatal error: authtoken.secret could not be written
Is the error I got, and a warning before it:
WARNING: failed to drop privileges (kernel may not support required prctl features), running as root
Loci
July 12, 2022, 4:06pm
4
Oh hmm, tbh i didnt test it much but it’s “worked” for a while.
Try commenting out lines until it works for you, my guess is ProtectHome
or more likely the SystemCallFilter
/ CapabilityBoundingSet
as these are strict.
I’ll check tomorrow when I’m back at my kit.
Loci
July 13, 2022, 8:05am
5
The first issue sounds like it can’t write to /var/lib/zerotier-one
so we’ll add the following:
ProtectSystem=strict
ReadWritePaths=/var/lib/zerotier-one
I belive we can then fix your ‘drop priv’ issues by adding CAP_SETGID
and CAP_SETUID
to CapabilityBoundingSet
and prctl
to SystemCallFilter
. So we get:
CapabilityBoundingSet=CAP_NET_ADMIN CAP_SETGID CAP_SETUID
SystemCallFilter=@system-service @network-io prctl
We can actually block the other implied syscalls as well, many of these are duplicates though and can be removed when systemd-analyze is fixed.
SystemCallFilter=~@resources @reboot @raw-io @privileged @obsolete @mount @debug @cpu-emulation @clock
That works for me on Arch 5.18.10-hardened, joining and leaving, ssh etc. (I also have @swap
becuase I have no swap lol) but again, Ive not really tested this a ton. Might be worth running a strace
if you have any issues later.
At this point my full file is the following:
[Service]
### no-hang
TimeoutStopSec=5
### Sandboxing
NoNewPrivileges=yes
PrivateTmp=yes
ProtectHome=read-only
ProtectControlGroups=yes
ProtectKernelModules=yes
ProtectKernelTunables=yes
ProtectKernelLogs=yes
ProtectHostname=yes
ProtectUsers=yes
ProtectSystem=strict
ReadWritePaths=/var/lib/zerotier-one
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6 AF_NETLINK
CapabilityBoundingSet=CAP_NET_ADMIN CAP_SETGID CAP_SETUID
RestrictNamespaces=yes
RestrictRealtime=yes
RestrictSUIDSGID=yes
LockPersonality=yes
SystemCallArchitectures=native
SystemCallFilter=@system-service @network-io prctl
SystemCallFilter=~@swap @resources @reboot @raw-io @privileged @obsolete @mount @module @debug @cpu-emulation @clock
UMask=0077
This gives 4.2 OK
. There’s actually a bug in systemd-analyze which fails the SystemCallFilter checks, so ignore the fails if you have that (might be Arch only).
1 Like