DNSSec validation

Hello,
I'm trying to work with the DNSSec validation example in the unbound
tutorial [0]. My issue is that at some point it calls:
ub_ctx_add_ta_file() with a file called "keys" and that according to
the comment this is the "public keys for DNSSEC verification". However
what does that exactly mean? How do you obtain this list? I have a
high level understanding of dnssec, and I'd expect that if I set
there the file /etc/unbound/root.key it should be able to verify any
domain, is that correct? (it doesn't seem to work)

regards,
Nikos

[0]. http://www.unbound.net/documentation/libunbound-tutorial-6.html

Hi Nikos,

Hello, I'm trying to work with the DNSSec validation example in the
unbound tutorial [0]. My issue is that at some point it calls:
ub_ctx_add_ta_file() with a file called "keys" and that according
to the comment this is the "public keys for DNSSEC verification".
However what does that exactly mean? How do you obtain this list? I
have a high level understanding of dnssec, and I'd expect that if
I set there the file /etc/unbound/root.key it should be able to
verify any domain, is that correct? (it doesn't seem to work)

You need:

ub_ctx_set_option(ctx, "auto-trust-anchor-file:",
"/etc/unbound/root.key");

because that file is in the 'auto-trust-anchor-file' format.

(at least, I hope so, if the file is in the BIND-format, you need the
function ub_ctx_trustedkeys).

Best regards,
   Wouter

Thank you. I tried it, but in both cases I get the same error message:
Result is bogus: validation failure <www.nlnetlabs.nl. A IN>: no
signatures from 10.0.2.3 for trust anchor . while building chain of
trust

I increased debugging but I cannot really follow the log, which
contains entries like:
[1349253750] libunbound[3158:0] info: super is www.nlnetlabs.nl. A IN
[1349253750] libunbound[3158:0] info: autotrust process for . DNSKEY IN
[1349253750] libunbound[3158:0] debug: rrset failed to verify due to a
lack of signatures
[1349253750] libunbound[3158:0] debug: Failed to match any usable
anchor to a DNSKEY.
[1349253750] libunbound[3158:0] debug: autotrust: validate DNSKEY with
anchor: sec_status_bogus
[1349253750] libunbound[3158:0] debug: autotrust: dnskey did not verify.
[1349253750] libunbound[3158:0] debug: autotrust: write to disk: root.key.3158-0
[1349253750] libunbound[3158:0] debug: autotrust: replaced root.key
[1349253750] libunbound[3158:0] debug: rrset failed to verify due to a
lack of signatures
[1349253750] libunbound[3158:0] debug: Failed to match any usable
anchor to a DNSKEY.

regards,
Nikos

Hi Nikos,

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1

Hi Nikos,

Hello, I'm trying to work with the DNSSec validation example in
the unbound tutorial [0]. My issue is that at some point it
calls: ub_ctx_add_ta_file() with a file called "keys" and that
according to the comment this is the "public keys for DNSSEC
verification". However what does that exactly mean? How do you
obtain this list? I have a high level understanding of dnssec,
and I'd expect that if I set there the file
/etc/unbound/root.key it should be able to verify any domain,
is that correct? (it doesn't seem to work)

You need: ub_ctx_set_option(ctx, "auto-trust-anchor-file:",
"/etc/unbound/root.key"); because that file is in the
'auto-trust-anchor-file' format.

Thank you. I tried it, but in both cases I get the same error
message: Result is bogus: validation failure <www.nlnetlabs.nl. A
>: no signatures from 10.0.2.3 for trust anchor . while building
chain of trust

I increased debugging but I cannot really follow the log, which
contains entries like: [1349253750] libunbound[3158:0] info: super
is www.nlnetlabs.nl. A IN [1349253750] libunbound[3158:0] info:
autotrust process for . DNSKEY IN [1349253750] libunbound[3158:0]
debug: rrset failed to verify due to a lack of signatures
[1349253750] libunbound[3158:0] debug: Failed to match any usable
anchor to a DNSKEY. [1349253750] libunbound[3158:0] debug:
autotrust: validate DNSKEY with anchor: sec_status_bogus
[1349253750] libunbound[3158:0] debug: autotrust: dnskey did not
verify. [1349253750] libunbound[3158:0] debug: autotrust: write to
disk: root.key.3158-0 [1349253750] libunbound[3158:0] debug:
autotrust: replaced root.key [1349253750] libunbound[3158:0] debug:
rrset failed to verify due to a lack of signatures [1349253750]
libunbound[3158:0] debug: Failed to match any usable anchor to a
DNSKEY.

The trust anchor was working all along, just fine.

The server at 10.0.2.3, is your DNS resolver, and it does not have
DNSSEC enabled. Use unbound without it: comment out the
ub_ctx_resolvconf call. Unbound then goes into full resolver mode.
It is wasteful and you have no fast cache hits, but it'll work with
DNSSEC.

It would be better (especially for bigger sites or bigger usage) to
upgrade the upstream cache. Upgrade it to support DNSSEC. It does
not actually have to validate, but it needs to have dnssec-enabled
(for BIND) or unbound (has that enabled by default). You could also
have it validate - which is a good idea in case validation failures
need retries. If this is your ADSL box, it may simply not be fixable,
instead change your resolv.conf(DHCP) to perhaps the actual upstream
DNS server from your ISP (many today actually have DNSSEC). Another
is to deploy a separate resolver server for your network (that you
advertise via DHCP). And there are more ways to setup your network.

Best regards,
   Wouter

The trust anchor was working all along, just fine.
The server at 10.0.2.3, is your DNS resolver, and it does not have
DNSSEC enabled. Use unbound without it: comment out the
ub_ctx_resolvconf call. Unbound then goes into full resolver mode.
It is wasteful and you have no fast cache hits, but it'll work with
DNSSEC.

Now it is perfectly ok, thank you!

It would be better (especially for bigger sites or bigger usage) to
upgrade the upstream cache.

I'll notify the administrators here.

regards,
Nikos

Is there some portable way to obtain a DNSSEC trust anchor in a
system? It seems that unlike the other functions which set a default
when NULL, the NULL value in the _ta_file() causes a crash. Otherwise
is checking for /etc/unbound/root.key a sensible default?

regards,
Nikos

Hi Nikos,

The trust anchor was working all along, just fine.

Is there some portable way to obtain a DNSSEC trust anchor in a
system? It seems that unlike the other functions which set a
default

portable? I cannot help you with this, perhaps authors of those
systems can provide you with their answers.

when NULL, the NULL value in the _ta_file() causes a crash.
Otherwise is checking for /etc/unbound/root.key a sensible
default?

The unbound-anchor tool has a default and can be used to also keep
this key up to date. It is meant to be used by the operating system
(e.g. run at startup time), but you could also run it to get a key for
your program.

Best regards,
   Wouter

Hi Nikos,

I wish there was, but it seems we as a community have failed to make
that happen. The bind format was first, and unbound supports it, then it
added another format to be able to manage rolling the key. So now we
have two formats with two different feature sets.

I haven't yet figured out the best way to manage this. It is also
confusing because the same libunbound functions don't take the different
formats, and you have to change your library function depending on the
format.

Paul

Is there some portable way to obtain a DNSSEC trust anchor in a
system? It seems that unlike the other functions which set a
default

portable? I cannot help you with this, perhaps authors of those
systems can provide you with their answers.

I think this shouldn't be left on the unbound application developer.
Similarly to ub_ctx_hosts() and ub_ctx_resolvconf() there should be an
option to try some sensible defaults. E.g. try to find the unbound
root.key file, then try the bind one, and so on. Then patches for the
various unsupported systems will come to unbound from developers
working with them. Otherwise this discovery phase will be duplicated
on every project using unbound, and possibly with varying success.

The unbound-anchor tool has a default and can be used to also keep
this key up to date. It is meant to be used by the operating system
(e.g. run at startup time), but you could also run it to get a key for
your program.

I develop a dane library to be used with gnutls and I cannot really
run external applications. I'll try to do the root.key discovery, and
if not found I'll return an error to the library user.

regards,
Nikos

>> Is there some portable way to obtain a DNSSEC trust anchor in a
>> system? It seems that unlike the other functions which set a
>> default
> portable? I cannot help you with this, perhaps authors of those
> systems can provide you with their answers.

I think this shouldn't be left on the unbound application developer.
Similarly to ub_ctx_hosts() and ub_ctx_resolvconf() there should be an
option to try some sensible defaults. E.g. try to find the unbound
root.key file, then try the bind one, and so on. Then patches for the
various unsupported systems will come to unbound from developers
working with them. Otherwise this discovery phase will be duplicated
on every project using unbound, and possibly with varying success.

> The unbound-anchor tool has a default and can be used to also keep
> this key up to date. It is meant to be used by the operating system
> (e.g. run at startup time), but you could also run it to get a key for
> your program.

I develop a dane library to be used with gnutls and I cannot really
run external applications. I'll try to do the root.key discovery, and
if not found I'll return an error to the library user.

There are 2 problems I think:

1. where to look for the key, what is the default on each system (Debian stores it at X, Fedora at Y).

2. How do you know someone (malicious ?) on that system didn't leave a key in a place it shouldn't ?

And how do you know this key will actually be updated ?

Guessing for something which is that security sensitive doesn't seem like a good idea to me.

But it isn't as easy as shipping the PGP-key from IANA [0] with your application and just check a
signature of the key either I believe.

So I guess for now the best thing is for the user to specify where it is stored ? And let the
distribution specify a location in their package ?

[0] https://data.iana.org/root-anchors/

There are 2 problems I think:

1. where to look for the key, what is the default on each system (Debian stores it at X, Fedora at Y).

Yes, this is a problem not only between linux distributions but also
between applications software.

2. How do you know someone (malicious ?) on that system didn't leave a key in a place it shouldn't ?

Because the key came in through the package manager, and it should be
GPG signed? Though I agree that the application would not perform this
check and I don't think the application should do this check, just like
other applications don't run tripwire to check if they are compromised.

However, it would make sense for the validating resolver to check this
on startup, especially in FIPS mode. But if we do that, we cannot roll
the key when we detect this is happening (eg unbound-anchor wise) and
we must rely on the vendor for the updates, and for a machine that is
shelved for 15 years and misses a root key roll, there is currently no
recovery method.

But it isn't as easy as shipping the PGP-key from IANA [0] with your application and just check a
signature of the key either I believe.

Especially seeing that the PGP key there did not sign a simple text
version of the key, but seems to sign for the CA/X509 certs used for
the webserver used at data.iana.org.

So I guess for now the best thing is for the user to specify where it is stored ? And let the
distribution specify a location in their package ?

I think so. And then there is the additional problem of how you add your
own keys for those DNSSEC islands that are not part of the public DNS
view.

Paul

>There are 2 problems I think:
>
>1. where to look for the key, what is the default on each system (Debian stores it at X, Fedora at Y).

Yes, this is a problem not only between linux distributions but also
between applications software.

>2. How do you know someone (malicious ?) on that system didn't leave a key in a place it shouldn't ?

Because the key came in through the package manager, and it should be
GPG signed? Though I agree that the application would not perform this
check and I don't think the application should do this check, just like
other applications don't run tripwire to check if they are compromised.

However, it would make sense for the validating resolver to check this
on startup, especially in FIPS mode. But if we do that, we cannot roll
the key when we detect this is happening (eg unbound-anchor wise) and
we must rely on the vendor for the updates, and for a machine that is
shelved for 15 years and misses a root key roll, there is currently no
recovery method.

>But it isn't as easy as shipping the PGP-key from IANA [0] with your application and just check a
>signature of the key either I believe.

Especially seeing that the PGP key there did not sign a simple text
version of the key, but seems to sign for the CA/X509 certs used for
the webserver used at data.iana.org.

I'm still left wondering who came up with that. :slight_smile:

My best guess is at least certain people they know already had the PGP-key.

>So I guess for now the best thing is for the user to specify where it is stored ? And let the
>distribution specify a location in their package ?

I think so. And then there is the additional problem of how you add your
own keys for those DNSSEC islands that are not part of the public DNS
view.

So what you really want is for distributions to use something like unbound-anchor but it needs to
support updating other anchors (which it currently does not ?).

Then you let the user or distribution (when your application is packaged) specify what directory to look for the keys ?

The file contains the domainname the key belows to.

(I just looked at unbound-anchor, I didn't know it had the IANA-cert builtin and supports HTTPS)

DNSSEC validation on client machines is complicated anyway, you need the right time. But when you want to talk to a
NTP server you probably depend on DNS...

DNSSEC is great, but not simple. :wink:

One option, I think the closest to "platform-independent" would be distributing
the key with the library (like NSS does with builtin certs). Then you can use
ub_ctx_add_ta (see attached sample). Obvious drawback is that you have issue new
version if root key changes or implement key management on your own.

Alternatively, probe for default locations of the key file, then fallback to key
distributed with the library. Also, you could add unbound-anchor to the
distributed archive and run it in a post-install script.

Notes on unbound and defaults:

- I suggest to avoid using forwarder (ub_ctx_set_fwd) as most commonly deployed
recursive DNS resolvers at ISPs will fail for DNSSEC (usually due to DS
records). Instead use libunbound as full recursive resolver. It will take few
queries to get its cache heated, but it's rather quick unless you go over a very
slow network like Tor.
- Attempting to use ub_ctx_hosts() with the default locations on the other hand
might be a good idea in preserving user's mappings for local machines, etc.
- Some distros like Fedora, RHEL and clones distribute unbound with root
anchors, some like Debian/Ubuntu don't. But I generally wouldn't count on the
key being present on a typical user's machine.

Ondrej

(attachments)

unbound-test.c (3.96 KB)

Ondrej Mikle wrote:

- Some distros like Fedora, RHEL and clones distribute unbound with root
anchors, some like Debian/Ubuntu don't. But I generally wouldn't count on the
key being present on a typical user's machine.

it's true that we (debian) don't distribute a root anchor _file_
embedded in the unbound package, but we invoke unbound-anchor in the
postinst script, so a typical/successful install will have the root TA
present in /var/lib/unbound/root.key.

There are 2 problems I think:
1. where to look for the key, what is the default on each system (Debian stores it at X, Fedora at Y).

That's the problem this approach would actually solve. You wouldn't need
to know that because the Debian maintainer would configure the library
with the correct paths and the same for fedora. We use that approach in
gnutls for quite some time with success.

2. How do you know someone (malicious ?) on that system didn't leave a

key in a place it shouldn't ?

You don't. You rely on your maintainer to correctly compile the package
for you. If you don't trust him, then you shouldn't be using this OS anyway.

And how do you know this key will actually be updated ?

That's why I suggested this to be handled in libunbound. So that
maintainers set the correct path, of the file that will be updated, at
compile time.

All the problems you mention are not because of my suggestion, they are
already there, but each and every application developer has to deal with
them. I think if unbound deals with it centrally it would be a good
thing for everyone using the library (I could provide an initial patch
if you're interested).

Guessing for something which is that security sensitive doesn't seem like a good idea to me.
But it isn't as easy as shipping the PGP-key from IANA [0] with your application and just check a
signature of the key either I believe.

I don't think having each application ship its own root keys can be a
realistic solution.

regards,
Nikos

That's the problem this approach would actually solve. You wouldn't need
to know that because the Debian maintainer would configure the library
with the correct paths and the same for fedora. We use that approach in
gnutls for quite some time with success.

I would be happy if libunbound had a compile time option for the root
and dlv keys, or perhaps better, a key directory. That way, if someone
configures custom key (manually or via puppet) then all applications
would know about those keys, whereas otherwise, it would depend on
unbound as a daemon to load these.

Note you should still run a daemon, and forward the appliction's use
via libunbound to the daemon, so all apps basically re-use a cache.

2. How do you know someone (malicious ?) on that system didn't leave a

key in a place it shouldn't ?

You don't. You rely on your maintainer to correctly compile the package
for you. If you don't trust him, then you shouldn't be using this OS anyway.

Yes. This is similar to FIPS, though FIPS does take an extra step and
builds in some hmac files to prevent some tampering. But once root
access (with write access to disk) has leaked out, it's pretty much
over.

I don't think having each application ship its own root keys can be a
realistic solution.

that would in fact be the _worst_ solution.

Paul

Notes on unbound and defaults:

- I suggest to avoid using forwarder (ub_ctx_set_fwd) as most commonly deployed
recursive DNS resolvers at ISPs will fail for DNSSEC (usually due to DS
records).

Really? When google dns fixed DS handling, I thought basically all that
went away. Perhaps not when using opendns, but really, we can't support
opendns one way or the other.

It's generally better to try to use the DHCP obtained DNS as forwarder,
  as many hotspot block port 53 for all but their local resolver.

Instead use libunbound as full recursive resolver. It will take few
queries to get its cache heated, but it's rather quick unless you go over a very
slow network like Tor.

Yes, but with prefetching and hopefully running the libunbound in the
app with resolver 127.0.0.1, performance should be pretty good as most
of the root/TLD domains are already in the unbound daemon cache, and the
crypto for the libunbound instance is pretty cheap.

- Attempting to use ub_ctx_hosts() with the default locations on the other hand
might be a good idea in preserving user's mappings for local machines, etc.

Yeah, keep those. That's what I did as well for the openswan dnssec
patch.

- Some distros like Fedora, RHEL and clones distribute unbound with root
anchors, some like Debian/Ubuntu don't. But I generally wouldn't count on the
key being present on a typical user's machine.

See the other discussion about compiled in key locations for the
library. I think that's a good idea.

Paul