NSD + unbound on production nameserver (not internal nameserver)

Hi,

For the past week I've been unsuccessfully trying to replicate on a FreeBSD nameserver our old BIND configuration, replacing it with with NSD + unbound instead.

Apparently, this is not possible, since it looks like unbound doesn't work as an 'proxy/cache' front-end. But... let me tell you about our configuration first.

This is a pair of FreeBSD servers, running several jails. Each server runs a jail with a real, public IP address on a nameserver for external (not internal) nameservices. Several other jails, each with a private address space, run the customers' websites. So we host both DNS name service as well as hosting services on behalf of our customers.

With BIND, the configuration was as following:

- Be authoratitative for external requests. Deny recursion for those.
- Act as a caching nameserver for internal requests (from the many jails). Allow recursion only for them.
- Internal requests for the domains we're authoritative for would also go to BIND as well, since, from BIND's perspective, it matters little where the request comes from (e.g. public/private addressing is irrelevant for authoritative requests)

Now for unbound + NSD.

When I first started to read about unbound + NSD, I thought it would be simple — like a Varnish/Apache configuration. NSD would remain on a non-accessible port (say 53530) on the nameserver jail, while unbound would forward requests to it. For internal requests from the other jails, unbound would act as a recursive caching server — easy to setup. To avoid unnecessary requests to external nameservers when requesting information from domain names we are authoritative for, unbound would simply forward requests to NSD. Easy-peasy. That works quite well for *internal* requests. Now the final and crucial step: how to allow the general public to retrieve domain information that we're authoritative for by contacting unbound?

Apparently, this is impossible to do.

Jan-Piet asked this same question in 2008: http://unbound.net/pipermail/unbound-users/2008-February/000021.html
And Oliver Peter did the same, five years later: https://unbound.net/pipermail/unbound-users/2013-November/003075.html

None ever received a single answer.

Indeed, by carefully reading the principles behind the unbound + NSD configuration, it seems that it has been designed to deal only with the scenario of a corporate network that requires both some DNS caching (provided by unbound) and a few internal, private domains being served by NSD, which, however, are never accessible by the public at large.

In contrast, on its own, NSD can be (and definitely is) used as an authorative nameserver for publicly available domain records — but without the added 'protection' of having unbound in front of it. Thus, although it *seems* that unbound + NSD is *similar* to Varnish + Apache for the web, in fact it's a *different* solution.

If I'm completely wrong about this, then how can unbound + NSD be configured so that unbound is able to act as a 'proxy/caching' nameserver as a frontend to NSD for public domains for which it is authoritative?

Thanks in advance for any insights!

  - Gwyn

It isn't possible. Authoritative servers set the AUTH bit; caching resolvers do not. The only service that should be publicly accessible is the Authoritative server (i.e. nsd). The caching resolver (unbound) should be bound to some other IP address and accessible only to the servers you control. You do not need or want to provide a resolver for the world.

This is one of the many things where the design of BIND fails.

John

Hi Gwyneth,

Hi,

For the past week I've been unsuccessfully trying to replicate on a
FreeBSD nameserver our old BIND configuration, replacing it with
with NSD + unbound instead.

Apparently, this is not possible, since it looks like unbound
doesn't work as an 'proxy/cache' front-end. But... let me tell you
about our configuration first.

This is a pair of FreeBSD servers, running several jails. Each
server runs a jail with a real, public IP address on a nameserver
for external (not internal) nameservices. Several other jails, each
with a private address space, run the customers' websites. So we
host both DNS name service as well as hosting services on behalf of
our customers.

With BIND, the configuration was as following:

- Be authoratitative for external requests. Deny recursion for
those. - Act as a caching nameserver for internal requests (from
the many jails). Allow recursion only for them. - Internal requests
for the domains we're authoritative for would also go to BIND as
well, since, from BIND's perspective, it matters little where the
request comes from (e.g. public/private addressing is irrelevant
for authoritative requests)

Now for unbound + NSD.

When I first started to read about unbound + NSD, I thought it
would be simple — like a Varnish/Apache configuration. NSD would
remain on a non-accessible port (say 53530) on the nameserver jail,
while unbound would forward requests to it. For internal requests
from the other jails, unbound would act as a recursive caching
server — easy to setup. To avoid unnecessary requests to external
nameservers when requesting information from domain names we are
authoritative for, unbound would simply forward requests to NSD.
Easy-peasy. That works quite well for *internal* requests. Now the
final and crucial step: how to allow the general public to retrieve
domain information that we're authoritative for by contacting
unbound?

Apparently, this is impossible to do.

Yes, the unbound set-up is fine. What you do is put NSD on port 53
and make it the server for external requests. Internal requests go to
unbound (on another ip-address, for example an internal ip-address,
for example a 127.0.0.x freebsd-jail with unbound in it), and set
unbound to send queries to NSD with stub configuration (better than
forwards in case the customer's zones have delegations or indirection
to the outside internet).

Best regards,
   Wouter

Jan-Piet asked this same question in 2008:
http://unbound.net/pipermail/unbound-users/2008-February/000021.html

And Oliver Peter did the same, five years later:
https://unbound.net/pipermail/unbound-users/2013-November/003075.html

Hi Wouter,

John,

Thanks for the amazingly quick reply!

Aye, it looks like you're quite right on that. Oh well. By itself, NSD at least is safer than BIND in any case (no fear of misconfigurating it accidentally as a caching resolver) and probably it's simpler and more light-weight than BIND anyway, so it's relatively simple to replace one by the other. Also, it's very easy to replace one by the other. Maybe it makes no sense to have an additional level of DNS caching (for the outside world) anyway: possibly NSD is more than adequate to deal with all the traffic and cache incoming requests for which it is authoritative efficiently.

In our scenario, we might still benefit slightly from unbound running on a completely separate FreeBSD jail just to cache requests made by the other jails to the outside world. But this scenario is clearly not what the typical unbound + NSD tutorials show — it's just unbound running on its own, and NSD on its own at well, as completely separate services.

I can live with that. Thank you for your explanation!

Cheers,

  - Gwyn

I did performance testing of BIND vs nsd when I was first investigating it; nsd is more than capable of handling authoritative requests (by a full order of magnitude over BIND if I am remember correctly). Whether you use a single unbound cache or having one in each jail is pretty much a design choice, since unbound is also capable of superior performance than BIND.

If your different jails have very different usage profiles, that would argue for having a fully functional unbound instance for each, rather than any shared cache. There isn't a lot of point IMNSHO to having one unbound instance forward queries to another instance, unless you have a specific reason for it (like firewall rules).

John