diff --git a/contrib/systemd/roothints-sig.sh.in b/contrib/systemd/roothints-sig.sh.in new file mode 100644 index 000000000..b903f795b --- /dev/null +++ b/contrib/systemd/roothints-sig.sh.in @@ -0,0 +1,10 @@ +#!/bin/bash + +if [ "$(md5sum '@UNBOUND_RUN_DIR@/root.hints' | cut -d' ' -f1)" = "$(cat '@UNBOUND_RUN_DIR@/root-hints.md5')" ]; then + exit 0 +else + command logger "Error (unbound-roothints): root-hints.md5 does not match root.hint's signature!" + # This line adds a notification when the sigs don't match! + # notify-send "Error (unbound-roothints): root-hints.md5 does not match root.hint's signature!" + exit 1 +fi diff --git a/contrib/systemd/unbound-anchor.service.in b/contrib/systemd/unbound-anchor.service.in new file mode 100644 index 000000000..1324b4486 --- /dev/null +++ b/contrib/systemd/unbound-anchor.service.in @@ -0,0 +1,92 @@ +; For further details about the directives used in this unit file, including +; the below, please refer to systemd's official documentation, available at +; https://www.freedesktop.org/software/systemd/man/systemd.exec.html. +; +; +; - `ProtectSystem=strict` implies we mount the entire file system hierarchy +; read-only for the processes invoked by the unit except for the API file +; system subtrees /dev, /proc and /sys (which are protected by +; PrivateDevices=, ProtectKernelTunables=, ProtectControlGroups=). +; +; - `PrivateTmp=yes` secures access to temporary files of the process, and +; makes sharing between processes via /tmp or /var/tmp impossible. +; +; - `ProtectHome=yes` makes the directories /home, /root, and /run/user +; inaccessible and empty for processes invoked by the unit. +; +; - `ProtectControlGroups=yes` makes the Linux Control Groups hierarchies +; (accessible through /sys/fs/cgroup) read-only to all processes invoked by +; the unit. It also implies `MountAPIVFS=yes`. +; +; - `RuntimeDirectory=unbound` creates a /run/unbound directory, owned by the +; unit User and Group with read-write permissions (0755) as soon as the +; unit starts. This allows unbound to store its pidfile. The directory and +; its content are automatically removed by systemd when the unit stops. +; +; - `NoNewPrivileges=yes` ensures that the service process and all its +; children can never gain new privileges through execve(). +; +; - `RestrictSUIDSGID=yes` ensures that any attempts to set the set-user-ID +; (SUID) or set-group-ID (SGID) bits on files or directories will be denied. +; +; - `RestrictRealTime=yes` ensures that any attempts to enable realtime +; scheduling in a process invoked by the unit will be denied. +; +; - `RestrictNamespaces=yes` ensures that access to any kind of namespacing +; is prohibited. +; +; - `LockPersonality=yes` locks down the personality system call so that the +; kernel execution domain may not be changed from the default. +; +; - With /etc/systemd/network/*.network a setting to make sure the network +; is not considered online too early, can reduce network unreachable +; errors on server start: +; [Link] +; RequiredForOnline=routable +; +[Unit] +Description=unbound-anchor +Documentation=man:unbound-anchor(8) +After=network-online.target +Wants=network-online.target +After=unbound-roothints.service +Wants=unbound-roothints.service +Before=unbound.service +OnFailure=logger "Error (unbound-anchor): Please check root anchor." + +[Install] +WantedBy=multi-user.target + +[Service] +User=unbound +Group=unbound +ExecCondition=@UNBOUND_RUN_DIR@/roothints-sig.sh +ExecStart=/bin/cp "/etc/trusted-key.key" @UNBOUND_ROOTKEY_FILE@ +ExecStart=@UNBOUND_SBIN_DIR@/unbound-anchor -f "/etc/resolv.conf" -r @UNBOUND_RUN_DIR@/root.hints -a @UNBOUND_ROOTKEY_FILE@ -c @UNBOUND_RUN_DIR@/icannbundle.pem +NotifyAccess=main +Type=oneshot +# TODO: Needs checking. Does unbound-anchor require net capabilities? +CapabilityBoundingSet=CAP_DAC_OVERRIDE CAP_NET_RAW CAP_NET_OVERRIDE +MemoryDenyWriteExecute=true +NoNewPrivileges=true +PrivateDevices=true +PrivateTmp=true +ProtectHome=true +ProtectClock=true +ProtectControlGroups=true +ProtectKernelLogs=true +ProtectKernelModules=true +ProtectKernelTunables=true +ProtectProc=invisible +ProtectSystem=strict +RuntimeDirectory=unbound +ConfigurationDirectory=unbound +StateDirectory=unbound +RestrictAddressFamilies=AF_INET AF_INET6 +RestrictRealtime=true +SystemCallArchitectures=native +RestrictNamespaces=yes +LockPersonality=yes +RestrictSUIDSGID=yes +ReadWritePaths=@UNBOUND_ROOTKEY_FILE@ +ReadOnlyPaths=/etc/trusted-key.key /etc/resolv.conf @UNBOUND_RUN_DIR@/root.hints @UNBOUND_RUN_DIR@/icannbundle.pem \ No newline at end of file diff --git a/contrib/systemd/unbound-anchor.timer.in b/contrib/systemd/unbound-anchor.timer.in new file mode 100644 index 000000000..85d97f375 --- /dev/null +++ b/contrib/systemd/unbound-anchor.timer.in @@ -0,0 +1,9 @@ +[Unit] +Description=Run unbound-anchor monthly + +[Timer] +OnCalendar=monthly +Persistent=true + +[Install] +WantedBy=timers.target diff --git a/contrib/systemd/unbound-roothints.service.in b/contrib/systemd/unbound-roothints.service.in new file mode 100644 index 000000000..e0a1de2f5 --- /dev/null +++ b/contrib/systemd/unbound-roothints.service.in @@ -0,0 +1,90 @@ +; For further details about the directives used in this unit file, including +; the below, please refer to systemd's official documentation, available at +; https://www.freedesktop.org/software/systemd/man/systemd.exec.html. +; +; +; - `ProtectSystem=strict` implies we mount the entire file system hierarchy +; read-only for the processes invoked by the unit except for the API file +; system subtrees /dev, /proc and /sys (which are protected by +; PrivateDevices=, ProtectKernelTunables=, ProtectControlGroups=). +; +; - `PrivateTmp=yes` secures access to temporary files of the process, and +; makes sharing between processes via /tmp or /var/tmp impossible. +; +; - `ProtectHome=yes` makes the directories /home, /root, and /run/user +; inaccessible and empty for processes invoked by the unit. +; +; - `ProtectControlGroups=yes` makes the Linux Control Groups hierarchies +; (accessible through /sys/fs/cgroup) read-only to all processes invoked by +; the unit. It also implies `MountAPIVFS=yes`. +; +; - `RuntimeDirectory=unbound` creates a /run/unbound directory, owned by the +; unit User and Group with read-write permissions (0755) as soon as the +; unit starts. This allows unbound to store its pidfile. The directory and +; its content are automatically removed by systemd when the unit stops. +; +; - `NoNewPrivileges=yes` ensures that the service process and all its +; children can never gain new privileges through execve(). +; +; - `RestrictSUIDSGID=yes` ensures that any attempts to set the set-user-ID +; (SUID) or set-group-ID (SGID) bits on files or directories will be denied. +; +; - `RestrictRealTime=yes` ensures that any attempts to enable realtime +; scheduling in a process invoked by the unit will be denied. +; +; - `RestrictNamespaces=yes` ensures that access to any kind of namespacing +; is prohibited. +; +; - `LockPersonality=yes` locks down the personality system call so that the +; kernel execution domain may not be changed from the default. +; +; - With /etc/systemd/network/*.network a setting to make sure the network +; is not considered online too early, can reduce network unreachable +; errors on server start: +; [Link] +; RequiredForOnline=routable +; +[Unit] +Description=unbound-roothints +Documentation=man:unbound(8) +After=network-online.target +Wants=network-online.target +Before=unbound-anchor.service +Before=unbound-chown.service +Before=unbound.service +OnFailure=logger "Error (unbound-roothints): Please check root hints." + +[Install] +WantedBy=multi-user.target + +[Service] +User=unbound +Group=unbound +ExecStart=/bin/curl -o @UNBOUND_RUN_DIR@/root.hints https://www.internic.net/domain/named.cache +ExecStart=/bin/curl -o @UNBOUND_RUN_DIR@/root-hints.md5 https://www.internic.net/domain/named.cache.md5 +ExecStart=/bin/curl -o @UNBOUND_RUN_DIR@/icannbundle.pem https://data.iana.org/root-anchors/icannbundle.pem +NotifyAccess=main +Type=oneshot +CapabilityBoundingSet=CAP_NET_RAW CAP_NET_OVERRIDE +MemoryDenyWriteExecute=true +NoNewPrivileges=true +PrivateDevices=true +PrivateTmp=true +ProtectHome=true +ProtectClock=true +ProtectControlGroups=true +ProtectKernelLogs=true +ProtectKernelModules=true +ProtectKernelTunables=false +ProtectProc=invisible +ProtectSystem=strict +RuntimeDirectory=unbound +ConfigurationDirectory=unbound +StateDirectory=unbound +RestrictAddressFamilies=AF_INET AF_INET6 +RestrictRealtime=true +SystemCallArchitectures=native +RestrictNamespaces=yes +LockPersonality=yes +RestrictSUIDSGID=yes +ReadWritePaths=@UNBOUND_RUN_DIR@/root.hints @UNBOUND_RUN_DIR@/root-hints.md5 @UNBOUND_RUN_DIR@/icannbundle.pem \ No newline at end of file diff --git a/contrib/systemd/unbound-roothints.timer.in b/contrib/systemd/unbound-roothints.timer.in new file mode 100644 index 000000000..b4d4ced8e --- /dev/null +++ b/contrib/systemd/unbound-roothints.timer.in @@ -0,0 +1,9 @@ +[Unit] +Description=Run root.hints monthly + +[Timer] +OnCalendar=monthly +Persistent=true + +[Install] +WantedBy=timers.target diff --git a/contrib/unbound.service.in b/contrib/unbound.service.in index b05e2c959..257891043 100644 --- a/contrib/unbound.service.in +++ b/contrib/unbound.service.in @@ -50,6 +50,11 @@ Documentation=man:unbound(8) After=network-online.target Wants=network-online.target Before=nss-lookup.target +# These two are needed for systemd-managed root.hints and trusted-key.key updates. +#After=unbound-roothints.service +#Wants=unbound-roothints.service +#After=unbound-anchor.service +#Wants=unbound-anchor.service [Install] WantedBy=multi-user.target