NLnetLabs / unbound

Unbound is a validating, recursive, and caching DNS resolver.
https://nlnetlabs.nl/unbound
BSD 3-Clause "New" or "Revised" License
3.15k stars 359 forks source link

unbound-anchor default configuration file #257

Closed sibeream closed 3 years ago

sibeream commented 4 years ago

Hello everyone,

There is a possible conflict for unbound-anchor used ports with SELinux policy. There is a bug filed in Red Hat Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1830625

In that particular example, unbound-anchor tries to use port 61000, which is not allowed by the SELinux policy. I was looking for a way to provide a default configuration file to avoid that port, but only found a way to provide configuration using -C option.

I would like to propose the following behavior:

  1. If a configuration file is specified with -C option, use specified one
  2. else If /etc/unbound/unbound-anchor.conf file exists, use it
  3. else don't use a configuration file

I believe this approach will make the tool more flexible in terms of different Linux distributions since they can have different SELinux policies, so maintainers will be able to create proper configurations. I can prepare a patch to implement that behavior. I just want to be sure that this approach makes sense for the community.

gthess commented 3 years ago

Hi, Since the option to use a configuration file with -C is already there I don't see why we would need a specific configuration file for unbound-anchor.

pemensik commented 3 years ago

Hi @gthess , we consider duplication of values already set in the system as inefficient. We would have to include some ranges in a configuration file. We currently do not use configuration file for unbound-anchor or unbound-host. They all should use the range.

Because that range could be modified by a system administrator, it could be different on some machines. Administrator would have to change sysctl ip_local_port_range AND to adjust matching values both in unbound.conf, unbound-anchor.conf and maybe some others. All such changes would have to be done manually, instead of just following the system settings.

Would configure option to enable such behaviour work better? It might not be enabled by default, but we would like to enable it instead of providing multiple configuration files with fixed numbers.

pemensik commented 3 years ago

I have to add, ~30k possible values should be more than enough for tools like unbound-anchor or unbound-host. We would like to still allow overriding autodetected ranges from configuration file, but without mandatory settings on selinux enabled machines.

This change should also affect any third party tools linking to unbound libraries, such as libreswan, getdns and openvswitch. I think it is better to have good defaults than to force manual configuration to all those tools.

gthess commented 3 years ago

Hi @pemensik, first of all I appreciate the further feedback.

It is my understanding that this kernel range is used by the kernel when a program does not provide its own port. In Unbound's case, for UDP communication, Unbound picks its own ports as port randomization is an important part of DNS over UDP. It is my understanding that this range is also used by SELinux for convenience.

I believe we both agree that the change we discuss here is not for unbound but for unbound tools like unbound-anchor and unbound-host instead. Both unbound-anchor and unbound-host however use libunbound to perform any DNS quering. We wouldn't want a universal change there even with configure to change unbound's behavior. So even if we patch libunbound and thus the accompanying tools, you would still need the appropriate values that you already ship in unbound.conf for the resolver deamon.

I would say I could look into a configure option for libunbound (and accompanying tools like unbound-anchor and unbound-host) to explicitly use that range for selecting UDP ports.

These tools are mainly used for one-off queries, but I also see mentions for other applications like libreswan which rely on libunbound for DNS quering. I would be hesitant to half the random space (also given the recent UDP derandomization attacks; SAD DNS) in that case. But then I realize that AFAIK unbound is already shipped like that to conform with SELinux so it wouldn't matter in your case I suppose.

Was the proposed kernel value (/proc/sys/net/ipv4/ip_local_port_range) by @sibeream the canonical place to get the desired range wrt SELinux?

pemensik commented 3 years ago

Correct, we already narrowed port range used even by unbound. It matches the default on Fedora system net.ipv4.ip_local_port_range = 32768 60999. It is enforced by SELinux by default so there is not different way. I think that is okay, ultimate fix to SAD DNS is not wider port range but DNSSEC signatures. That is the reason for unbound libraries use in most software anyway.

It would not change anything with SELinux policy in place anyway, just occasional denied port would not show in audit logs. Not sure how it is related to selinux ranges. I will try to test it.

sibeream commented 3 years ago

In case you'll decide to proceed with this, I've created a draft PR which includes the configure option.

gthess commented 3 years ago

Thanks @sibeream! It will prove useful.

sibeream commented 3 years ago

Hi @gthess,

Can we get back to this request once again, please.

I see your point about narrowing the random port space, but as you mentioned it's done anyway in the configuration as well as SELinux policy. Since the actual narrowing is effectively done by SELinux and there are no other option for the libunbound other then to comply with the SELinux policy, this change (IMO) is not actually narrowing the port range but make libunbound to automatically comply with the system limitations on SELinux enabled distributions. I think this will make system administrator life easier on SELinux enabled systems, since they will only need to change port configuration system wide.

Since this feature is optional, disabled by default and can be enabled only in configure time it seems to me highly improbable to bring an unexpected behavior to the system administrators. Inclusion of this feature is up to package maintainers who in most cases should understand what they are doing. To help prevent misuse of this feature I can take a look on improving the informativeness of the comments in autoconfig and configure scripts so it'll be easier for the person who build the package (including package maintainers) to properly decide if this should be enabled or the default configuration should be used.

If you see any other potential problem with this change, please point it out, I'll work on the solution to solve that.

gthess commented 3 years ago

Hi @sibeream, Sure, I was under the impression that we are waiting for @pemensik to verify/test the selinux ranges. Apart from that I just left some feedback for your pull request.

letoams commented 3 years ago

Why is unbound-anchor and unbound-host not using the regular ephemeral port request mechanism ? These are not long running daemons. unbound-anchor uses DNSSEC or the ICANN certificate bundle, and unbound-host is a debug tool. Neither really need special treatment of ephemeral ports ?

gthess commented 3 years ago

These tools are built on top of the resolver library which itself handles the outgoing ports (for UDP). There is the configure option --disable-explicit-port-randomisation which lets the kernel pick a random port but that would be applied to both unbound and libunbound tools.

pemensik commented 3 years ago

It seems to me selinux policy contains just copy of ephemeral range, not some form of link to in-kernel values stored in /proc/sys/net/ipv4/ip_local_port_range. It is still the best value we can use.

But I agree with Paul @letoams, it might make sense to opt-in to standard emphemeral port algorithm from short lived programs like unbound-host, unbound-anchor and similar. Explicit port setting might not be necessary, if we could instruct unbound library to bind to port=0 for outgoing sockets and leave it to the OS. I think original idea was to widen range of outgoing ports to choose from. If we narrow it back to ephemeral range and the OS does not do a bad job at randomizing outgoing ports, all this logic might not be necessary.

Does any supported OS do a bad job at port randomizing? Are ports predictable on any reasonably modern system? Were it tested on different platforms recently?

sibeream commented 3 years ago

I fixed the issues pointed in your feedback for the PR. Do we want to move forward with that or the information stated here by @pemensik changes the approach we want to take with this one?

I see the problem that SELinux contains just a copy of the ephemeral range. But it looks for me as the problem in SELinux not respecting the system configuration, not in the solution we came with. I would rather create a bug for SELinux to respect the system configuration (watch that configuration updated) than make other packages respect SELinux as a source of this kind of configuration information.

Regarding the opting-in to the standard ephemeral port algorithm. I agree with @pemensik that the fact of narrowing port range back to an ephemeral range makes sense to let the OS do its job. I think another configure option can be introduced, which will make tools like unbound-host, unbound-anchor, and similar to utilize the OS-provided mechanism of port randomization. I'm not sure if it should be done as a part of the changes we discussing here.

I see the current problem is the fact that the current randomization algorithm process doesn't respect system configuration and I would like to have a way (PR) to have it fixed. Being able to use OS-provided randomization looks to me as another (good in my opinion) feature, which should be worked on separately. I don't think the internal (libunbound) randomization will be deleted from the code in favor of the OS-provided one. So even if the OS-provided randomization option will arrive it has nothing to do with the problem we have with the internal randomization not respecting the system configuration.

@gthess any thoughts on that? What should be done to proceed with the PR?

gthess commented 3 years ago

@sibeream: the PR looked good to me from the first review, minus the feedback. I was scheduling to do a final pass closer to a release date but I can do it earlier if it would help with testing from your part.

@pemensik: I believe the OS in this case is redhat, right? So the linux kernel shipped with each version. Since 2007 the linux kernel has UDP port randomization support (https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=32c1da70810017a98aa6c431a5494a302b6b9a30). The most recent UDP kernel vulnerability was SAD DNS (https://www.saddns.net/). Not a direct attack on randomization, but in case of a vulnerability I guess it depends on what is easier to patch and ship, a backport of the kernel or a backport of unbound.

Since the PR is specifically considered for redhat shipped systems, I would prefer for you to tell me which is the preferred option going forward. If you decide on using the --disable-explicit-port-randomisation configure option, I wouldn't want to include the PR's configure option if it is not going to be used.

For reference, the --disable-explicit-port-randomisation configure option was contributed for OpenBSD systems (https://github.com/NLnetLabs/unbound/commit/5aaa5e253deac0f6ea0d45305668b20031f4610e) and this is what they use on their unwind resolver (uses libunbound) and unbound itself:

I can't comment though on the effectiveness of port randomization between linux and openbsd kernels.

sibeream commented 3 years ago

@gthess I'm sorry for the late reply. It's fine for me to do a final pass closer to a release date. I just needed some form of confirmation that the changes will make their way to the release, so I can start backporting patches to the distributions. Thanks!

gthess commented 3 years ago

@sibeream: Just reviewed your PR, looks good with some nits! @pemensik: Could you verify that the configure option that the PR introduces is going to be used? If so this could go in the next release.

gthess commented 3 years ago

Hi @pemensik, just approved @sibeream's PR for this (#415). Any update on how you would like to proceed?

tjanez commented 3 years ago

FWIW, @sibeream added the changes in #415 to Fedora's unbound package as a patch on Apr 24 2021.

Effectively, this is what will be used in the upcoming Fedora 35.

gthess commented 3 years ago

Thanks for the information! Now with #415 merged, this can be closed.