Skip to content

Add other services to contrib. Patch unbound.service to link to these services. Add timers.#1387

Open
ninetailedtori wants to merge 5 commits intoNLnetLabs:masterfrom
ninetailedtori:chown-trustedkey
Open

Add other services to contrib. Patch unbound.service to link to these services. Add timers.#1387
ninetailedtori wants to merge 5 commits intoNLnetLabs:masterfrom
ninetailedtori:chown-trustedkey

Conversation

@ninetailedtori
Copy link

Adds unbound-roothints.service, including a root.hints signature checking stage pre-unbound-anchor. Adds unbound-anchor.service, which calls unbound-anchor to generate a new rootkey file based on the system default from dnssec-anchors package. Adds unbound-chown.service which chown's the unbound run dir, unbound chroot dir and unbound rootkey file to unbound:unbound, in line with the Linux ACLs, which then supports a tougher sandbox on the systemd services.

Hopefully I've not f-ed something up, but I never trust myself fully, so fingers crossed. Would love some review of the systemd unit hardening as well. Due to complexity and safety, I didn't want to change the services that did similar actions on different params into parameter services, firstly as it's quite easy to abuse those services, and secondly I'd have to define targets, and thirdly it doesn't fully work for root-hints since we're renaming files in the curl command as well, which requires two parameter variables, and systemd @param services don't work for more than one param variable, but I'd be curious if it's possible to do safely and neatly.

And finally, not even sure this is something you want to add, but it does solve a bunch of issues with file ownership with the systemd unit when it's locked down to low capabilities and chrooted, but then struggles to access the trust anchor file or its own chroot/run dir where it also generates tempfiles (mostly for trust anchor files as well). This should fix everything on those bugs? Works for me at the least.

Copy link
Member

@gthess gthess left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this seems like a full chain of systemd units to handle root-hints, root-anchor and provide unbound as a service.

My main points are:

  1. This would need it's own directory under /contrib to put all those files in and a readme file to explain what is expected if those units are installed.
  2. I would not touch the /contrib/unbound.service.in file since it can be already in use in some users' system, instead provide an unbound.service.in file inside the above mentioned directory.
  3. For the chown service, I would skip it altogether and instead run the unbound-anchor service as the user unbound.

You can also find some inline comments in the files as part of this review.

[Service]
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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

icannbundle.pem does not seem to be used somewhere

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was mentioned in the documentation inline, is this incorrect?

Copy link
Author

@ninetailedtori ninetailedtori Dec 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@UNBOUND_ROOTCERT_FILE@
       The trusted self-signed certificate that is used to verify the
       downloaded DNSSEC root trust anchor.
       You can update it by fetching it from
       https://data.iana.org/root-anchors/icannbundle.pem (and validate it).
       If the file does not exist or is empty, a builtin version is used.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right, I forgot that it uses that location by default. But you can also explicitly pass it as the -c option to show its usage.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added it, it'll be in the next commit!


[Service]
ExecCondition=@UNBOUND_RUN_DIR@/roothints-sig.sh
ExecStart=/bin/cp "/etc/trusted-key.key" @UNBOUND_ROOTKEY_FILE@
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is this /etc/trusted-key.key coming from?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comes from an included file, owned by dnssec-trustanchors, as is documented in the official archlinux packaging for unbound in its PKGBUILD. I am not sure if other systems that use systemd also have this file included or not?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to be very arch specific. Other distributions have other packages with other filenames to keep track of the root trust anchor. Maybe the folder should be named something mentioning systemd and arch together?

But also by copying this information over you mess with the RFC5011 metadata that Unbound has populated the file with in the meantime.

If you trust this file, why do you do the whole anchor dance and not just using that file with the truch-anchor-file option? I expect that the trusted-key.key will be regularly updated in a rolling distro as arch.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not too sure actually. Is it not better to generate a new key based off of the original anchor? This one rarely updates whereas my service generates a new trust key for dnssec every unbound restart. Shouldn't cycling keys be more secure?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://man.archlinux.org/man/dnssec-trust-anchors.d.5.en for more info on the system-based one, I'd welcome some help comprehending the dnssec toolchain though. Is it not best to cycle them for security? Means that if a dnssec key gets compromised it can easily be cycled with a restart of the dns service.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, there's a reason we do at the least have to clone the file:
When doing dnssec, unbound itself edits the key as well, and requires readwrite. This can't be done with the base key as it's a system-restricted root-access key, which should not be touched. The unbound/trusted-key CAN be regenerated, and that's fine for that though.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The root key is rarely updated itself, you can check https://www.iana.org/dnssec/files.

Replacing the Unbound-managed file with each restart defeats the purpose of the RFC5011 logic. New keys (that are not part of the file initially but rather discovered by Unbound) are kept track of and there are timers on when they can be considered for signing. Also timers for revocation etc.
RFC5011 is meant for resolvers that are fairly often online (so that they can keep track of key changes) and that they have no other means of updating their trust anchor (like a system/software update for example).

You can start with copying over the packaged key, but after that you can let Unbound handle it. If you are copying it over each time there is no reason for the automatic part since all the timer information is wiped clean.

@gthess gthess self-assigned this Dec 30, 2025
@ninetailedtori
Copy link
Author

Thanks, this seems like a full chain of systemd units to handle root-hints, root-anchor and provide unbound as a service.

My main points are:

  1. This would need it's own directory under /contrib to put all those files in and a readme file to explain what is expected if those units are installed.

  2. I would not touch the /contrib/unbound.service.in file since it can be already in use in some users' system, instead provide an unbound.service.in file inside the above mentioned directory.

  3. For the chown service, I would skip it altogether and instead run the unbound-anchor service as the user unbound.

You can also find some inline comments in the files as part of this review.

Moving unbound.service.in isn't possible to implement globally safely? Would it be best for us to simply leave that entirely? Or alternatively: symlink the service in contrib/ to contrib/systemd/?

@ninetailedtori
Copy link
Author

Also, moving unbound-anchor to run as unbound only works if unbound owns their entire folder. This is thus done best either:

  • if you run as root then chown it manually, OR;
  • if you edit unbound-anchor itself to do the chowning by itself!

@gthess
Copy link
Member

gthess commented Dec 30, 2025

Moving unbound.service.in isn't possible to implement globally safely? Would it be best for us to simply leave that entirely? Or alternatively: symlink the service in contrib/ to contrib/systemd/?

I would want to keep contrib/unbound.service.in intact because it is probably already in use by users. Having your own service file in a directory, you have the freedom to describe any process there wrt other services as you do.

@ninetailedtori
Copy link
Author

Right, that works quite well, I suppose? Should I edit the main service wants still to my specs? Commented out, until a user decides to use my services?

Comment out additional units in unbound.service.in.
Also add reference to icannbundle.pem to unbound-anchor.service.in.

Signed-off-by: Toria <ninetailedtori@uwu.gal>
…p natively (safer than needing sudoers access AND config).
@gthess
Copy link
Member

gthess commented Dec 31, 2025

I would still keep contrib/unbound.service.in intact and instead use a contrib/systemd-arch/unbound.service.in. Together with a README there to document how all the services tie together and why it is arch specific.

If you want to make it non-arch specific you can either have a variable on where to find the system's trust anchor, or just bootstrap without it with only unbound-anchor. But then you get to a philosophical discussion on which DNSSEC key to trust if the distribution already ships one. Maybe if you don't provide a system distributed key, unbound-anchor bootstraps itself; this is me thinking aloud btw.

If you go for the non-arch specific way, I guess the comments can stay in contrib/unbound.service.in and point to the directory and the README for the rest of the unit files.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants