NLnetLabs/unbound

`unbound` returns `NOERROR` when signature inception timestamp is set to future

justahero opened this issue · 2 comments

Describe the bug

After signing a zone file with the signature inception timestamp set to the future (+1 hour from current time), fetching the signed record using unbound as a validating resolver returns the NOERROR return code instead of SERVFAIL. According to RFC 4035, section 5.3.1 one of the conditions to check for the inception field is:

The validator's notion of the current time MUST be greater than or equal to the time listed in the RRSIG RR's Inception field.

To reproduce
Steps to reproduce the behavior:

  1. set up name server (e.g. bind) with DNSSEC enabled
  • generate KSK + ZSK keys using ldns-keygen
  • sign zone using ldns-signzone with inception (+1h in the future) and expiration (+4h in the future) timestamps set using the Unix timestamp format (according to documentation in ldns-signzone.c)
  • create DS record using ldns-key2ds with the signed zone file
  1. set up unbound as validating resolver
  • set up trust anchor from name server
  1. use dig to query unbound resolver
dig +recurse +nodnssec +noadflag +nocdflag @172.18.0.3 SOA .

where @172.18.0.3 is the IP of the validating resolver unbound

Please note the given IPs are dynamically assigned, they are not too important for the setup.

The resulting output of dig is

; <<>> DiG 9.18.24-1-Debian <<>> +recurse +nodnssec +noadflag +nocdflag @172.18.0.3 SOA .
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 38239
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;.				IN	SOA

;; ANSWER SECTION:
.			86214	IN	SOA	primary0.nameservers.com. admin0.nameservers.com. 2024010101 1800 900 604800 86400

;; Query time: 1 msec
;; SERVER: 172.18.0.3#53(172.18.0.3) (UDP)
;; WHEN: Wed Jul 10 08:57:53 UTC 2024
;; MSG SIZE  rcvd: 94

The unbound.conf file contains:

server:
    verbosity: 4
    use-syslog: no
    interface: 0.0.0.0
    access-control: 172.18.0.0/16 allow
    root-hints: /etc/root.hints
    pidfile: /tmp/unbound.pid
    ede:  no
    trust-anchor-file: /etc/trusted-key.key

remote-control:
    control-enable: noroot

Expected behavior

It's expected that unbound responds with SERVFAIL to signal an invalid request. Furthermore it should not include the SOA record in its ANSWER section, because the CD bit is unset (according to RFC 4035 section 5.5).

System:

  • Unbound version: 1.17.1
  • OS: Ubuntu 22.04
  • unbound -V output:
unbound -V
Version 1.17.1

Configure line: --build=aarch64-linux-gnu --prefix=/usr --includedir=${prefix}/include --mandir=${prefix}/share/man --infodir=${prefix}/share/info --sysconfdir=/etc --localstatedir=/var --disable-option-checking --disable-silent-rules --libdir=${prefix}/lib/aarch64-linux-gnu --runstatedir=/run --disable-maintainer-mode --disable-dependency-tracking --with-pythonmodule --with-pyunbound --enable-subnet --enable-dnstap --enable-systemd --with-libnghttp2 --with-chroot-dir= --with-dnstap-socket-path=/run/dnstap.sock --disable-rpath --with-pidfile=/run/unbound.pid --with-libevent --enable-tfo-client --with-rootkey-file=/usr/share/dns/root.key --disable-flto --enable-tfo-server
Linked libs: libevent 2.1.12-stable (it uses epoll), OpenSSL 3.0.11 19 Sep 2023
Linked modules: dns64 python subnetcache respip validator iterator
TCP Fastopen feature available

BSD licensed, see LICENSE in source package for details.
Report bugs to unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues

Additional information

The setup was tested with both bind & unbound configured as DNSSEC enabled name server. In both cases the return code was NOERROR instead of SERVFAIL.

It is because the test uses a too small time value change. With larger values, Unbound would have made it bogus. It should of course become bogus, because the inception is in the future. For such a small change, Unbound has differential handling.

Assuming everyones timezone is broken, there is some leeway allowed in the signature times. This is to stop operational snafus from causing false positives in dnssec failures. That would cause operation overhead in trying to fix that. To solve this Unbound allows some leeway on the signature. It can be configured, with the options val-sig-skew-min and val-sig-skew-max, in addition to these min and max options, Unbound attempts to use about 10% of the time to expiry as a leeway on the time stamp. For the case in question, that would have been a small value, 3h / 10, and then the val-sig-skew-min is an hour by default. This makes it apply an hour leeway, and this makes unbound accept the signature timestamps. The value of the default for val-sig-skew-min is chosen such, because the clock not having the precisely correct time is very common, in addition to hour change misconfiguration issues.

The man page for val-sig-skew-min and val-sig-skew-max:
https://unbound.docs.nlnetlabs.nl/en/latest/manpages/unbound.conf.html#unbound-conf-val-sig-skew-min
https://unbound.docs.nlnetlabs.nl/en/latest/manpages/unbound.conf.html#unbound-conf-val-sig-skew-max

@wcawijngaards

thank you for the information. Adjusting the inception timestamp to a value larger than 1 hour shows the expected behavior. Therefore closing this ticket.