FS#61163 - [unbound] enable systemd hardening
Attached to Project:
Community Packages
Opened by Remi Gacogne (rgacogne) - Sunday, 23 December 2018, 16:26 GMT
Last edited by Gaetan Bisson (vesath) - Thursday, 19 September 2019, 20:01 GMT
Opened by Remi Gacogne (rgacogne) - Sunday, 23 December 2018, 16:26 GMT
Last edited by Gaetan Bisson (vesath) - Thursday, 19 September 2019, 20:01 GMT
|
Details
Since we are currently providing the systemd service file
for Unbound, it would be nice to add some hardening options
to it. I have been running with these for a while without
any issue, and unless someone sees something wrong with them
I think it would make sense to add them to the service
file:
PrivateDevices=true PrivateTmp=true ProtectControlGroups=true ProtectHome=true ProtectKernelModules=true ProtectKernelTunables=true # not full to allow auto-trust-anchor-file to work correctly ProtectSystem=true NoNewPrivileges=true RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6 RestrictNamespaces=true SystemCallArchitectures=native |
This task depends upon
Closed by Gaetan Bisson (vesath)
Thursday, 19 September 2019, 20:01 GMT
Reason for closing: Implemented
Additional comments about closing: unbound-1.9.3-3 in [community]
Thursday, 19 September 2019, 20:01 GMT
Reason for closing: Implemented
Additional comments about closing: unbound-1.9.3-3 in [community]
CapabilityBoundingSet=CAP_IPC_LOCK CAP_NET_BIND_SERVICE CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_SYS_RESOURCE
MemoryDenyWriteExecute=true
NoNewPrivileges=true
PrivateDevices=true
PrivateTmp=true
ProtectHome=true
ProtectControlGroups=true
ProtectKernelModules=true
ProtectKernelTunables=true
ProtectSystem=strict
ReadWritePaths=@UNBOUND_SYSCONF_DIR@ @UNBOUND_LOCALSTATE_DIR@ /run @UNBOUND_RUN_DIR@
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
RestrictRealtime=true
SystemCallArchitectures=native
SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module mount @obsolete @resources
However we can't use upstream service directly because 'Type=notify' can work only for socket activation.
Note that Type=Notify should work as long as they call sd_notify(), which they do in daemon_fork(), so perhaps we could in fact use the upstream service directly?
You may need to pass '--enable-systemd' in configure and maybe 'use-systemd: yes' in unbound.conf.
--enable-systemd requires adding PKG_CONFIG="/usr/bin/pkg-config" in configure params otherwise it can't find libsystemd dependency.
'ReadWritePaths=@UNBOUND_SYSCONF_DIR@ @UNBOUND_LOCALSTATE_DIR@ /run @UNBOUND_RUN_DIR@' will result in
'ReadWritePaths=/etc /var /run /etc/unbound' which is definitely too broad and wrong. That would need patching as desired lines could be like this instead: 'ReadWritePaths=/etc/unbound /var/lib/unbound /run/unbound'.
With 'Type=Notify' executing 'systemctl start unbound' command hangs in terminal (although service is started correctly). Removing 'Type=Notify' fixes this issue.
That's all from me.
FS#59162The maintainer tried, then reverted it with the comment "Oh, well, Type=notify fails for me too: unbound never notifies anything to systemd and `systemctl start` is left hanging. We'll just get rid of PIDFile=... Sorry for the noise."
We can use upstream service and patch some lines with 'sed' or copy just the hardening parts to our own service.
https://github.com/NLnetLabs/unbound/blob/d29c1f06af38d71f0940531dddb90d9cf1b2f829/daemon/daemon.c#L663
Edit:
Missed https://bugs.archlinux.org/task/61163#comment175632 by Jake Kreiger which had already found all of this.
Sorry for the noise.
1/ we need to compile with '--enable-systemd' (with the right PKG_CONFIG env) ;
2/ we need to make sure that unbound doesn't chroot to "/etc/unbound" (the default) before calling sd_notify(), otherwise that fails because /run/systemd/notify does not exist inside the chroot. This can be done by setting chroot: "" in the configuration file.
Then if we want to use the provided unit file, we also need to disable the writing of the PID file, which is mostly useless once unbound is managed by systemd anyway. It needs to be disabled because unbound tries to write it before switching to the "unbound" user, while still running as root, but the file is owned by "unbound:unbound" and root doesn't have CAP_DAC_OVERRIDE anymore with the CapabilityBoundingSet applied, so it can't alter the file.
What if we removed the `Type=notify` line from upstream's service file and used that? Can either of you confirm that it works and comment on whether it achieves the desired level of hardening?
In last release (1.9.3) upstream finally made some systemd fixes:
https://github.com/NLnetLabs/unbound/commit/a90f173875baf9a40ec2f2860439f571c2f3e280
https://github.com/NLnetLabs/unbound/commit/06847ff3be18afe77a0bd3ac69a862253c9506c0
You can try building with "--enable-systemd" and taking upstream service file.
Wee can go back to your proposal from https://bugs.archlinux.org/task/61163#comment178585 and use upstream service file and remove Type=notify from it.
Here's simple PKGBUILD diff for that
Samples of new error mesasges that started with this release:
Using
ip-transparent: yes
leads to:
unbound[] warning: setsockopt(.. IP_TRANSPARENT ..) failed: Operation not permitted
Similarly there are now errors with other socket options which are new:
unbound[] warning: so-rcvbuf 1048576 was not granted. Got 425984. To fix: start with root permissions(linux) or sysctl bigger net.core.rmem_max(linux) or kern.ipc.maxsockbuf(bsd) values.
unbound[] warning: so-sndbuf 4194304 was not granted. Got 425984. To fix: start with root permissions(linux) or sysctl bigger net.core.wmem_max(linux) or kern.ipc.maxsockbuf(bsd) values.
I think there was misunderstanding. If you disable chroot then you don't need changing service type to simple.
In the diff I posted the assumption was to keep chroot intact while using upstream service file. Also as last comment shows ProtectKernelTunables is breaking some functionality and should be disabled.
Warnings:
I changed ip-transparent to
ip-freebind: yes
Which works fine without root.
I also fixed my sockopts via sysctl (net.core.wmem_max and net.core.rmem_max).
Error:
I needed to add (as per the default config in package now requiring it)
chroot: ""
Without this, (my original config) the service fails to start at all.
https://github.com/NLnetLabs/unbound/commit/ff8fd0be5c529e7a1b84e8c74426e9c531c0a8f8