I’ve unbound setup on FreeBSD 11.1 and I can’t figure out why “drill www.wilda.nsec.0skar.cz” gives SERVFAIL. The domain is from this (http://0skar.cz/dns/en) test site where it reports three failures (2a, 2b and 4). Any help would be appreciated.
Thanks
Sebastian
$ unbound -h
Version 1.6.7
linked libs: libevent 2.1.8-stable (it uses kqueue), OpenSSL 1.0.2n 7 Dec 2017
linked modules: dns64 respip validator iterator
DNSCrypt feature available
$ uname -a
FreeBSD dns.seby.io 11.1-RELEASE-p4 FreeBSD 11.1-RELEASE-p4 #0: Tue Nov 14 06:12:40 UTC 2017 root@amd64-builder.daemonology.net:/usr/obj/usr/src/sys/GENERIC amd64
$ unbound-host -f /usr/local/etc/unbound/root.key -v www.wilda.nsec.0skar.cz
...
validation failure <www.wilda.nsec.0skar.cz. A IN>: signature inception after expiration from 2001:1528:132:70::1 for key nsec.0skar.cz. while building chain of trust
...
I�ve unbound setup on FreeBSD 11.1 and I can�t figure out why "drill
www.wilda.nsec.0skar.cz" gives SERVFAIL. The domain is from this
(http://0skar.cz/dns/en) test site where it reports three failures (2a,
2b and 4). Any help would be appreciated.
When I run unbound-host, I get no errors,
./unbound-host www.wilda.nsec.0skar.czwww.wilda.nsec.0skar.cz -f
root.key -v -t A
www.wilda.nsec.0skar.czwww.wilda.nsec.0skar.cz has address
85.239.227.179 (secure)
Unbound performs serial arithmatic on the timestamps in the rrsig,
according to RFC.
(What does that mean? The timestamps are 32bit in the RRSIG, but the
value is interpreted relative to the current date. And what you cannot
do is express something like a point more than some number of years
future or past.)
$ unbound-host -v -t A -f /usr/local/etc/unbound/root.key www.wilda.nsec.0skar.cz
www.wilda.nsec.0skar.cz is an alias for flexi.oskarcz.net. (BOGUS (security failure))
flexi.oskarcz.net has address 85.239.227.179 (BOGUS (security failure))
validation failure <www.wilda.nsec.0skar.cz. A IN>: signature inception after expiration from 85.239.227.179 for key nsec.0skar.cz. while building chain of trust
FreeBSD 11.1:
$ unbound-host -v -f /usr/local/etc/unbound/root.key -t A www.wilda.nsec.0skar.cz
www.wilda.nsec.0skar.cz is an alias for flexi.oskarcz.net. (BOGUS (security failure))
flexi.oskarcz.net has address 85.239.227.179 (BOGUS (security failure))
validation failure <www.wilda.nsec.0skar.cz. A IN>: signature inception after expiration from 2001:1528:132:70::1 for key nsec.0skar.cz. while building chain of trust
Unbound performs serial arithmatic on the timestamps in the rrsig,
according to RFC.
(What does that mean? The timestamps are 32bit in the RRSIG, but the
value is interpreted relative to the current date. And what you cannot
do is express something like a point more than some number of years
future or past.)
Best regards, Wouter
Hello Wouter,
Thanks for the insight. Maybe this has something to with the platform?
Yes it is the compiler. Clang fails, gcc succeeds. I can make clang
succeed with a small code change together with the removal of -O2
(disabling clang's optimizer).
The code change is instead of if(incep - expi > 0) ..fail.. it now has
var=incep-expi; if(var > 0) ..fail..
Clangs optimizer seems to take the wrong branch in the if statement. If
I printout the value calculated, I get the correct output. Something
like if(!((incep-expi)&0x80000000)) ..fail.. does not trick the
optimizer into taking the right branch.
The code change is in the code repository.
CFLAGS=-g ./configure
This disables -O2 as well, with the current version of unbound.
Or as a workaround, maybe ignore this, perhaps with domain-insecure,
because it seems to only happen for the int32_t values of (1391084010 -
-823674496 > 0). And 2080 is uncommon in RRSIG timestamps.
Thanks so much for finding the problem. I've recompiled unbound with GNU gcc for now. It seamed like the simplest solution.
I never would have thought that the access to a internet service (to the end user) could be broken because of a compiler optimisation. Still so many things have to go "wrong" for this to happen.
The original coded uses non-portable undefined overflow behaviour
for signed integer arithmetic. The compiler is free to replace
"incep - expi > 0" with "incep > expi". The intermediate "var"
may in some cases avoid the problem, but this is still brittle
under optimization. To avoid non-deterministic behaviour unsigned
arithmetic must be used:
uint32_t incep;
uint32_t expi;
/*
* In serial number arithmetic a > b iff as unsigned integers mod 2^32
* we have (a - b) < (b - a)
*/
if ((incep - expi) < (expi - incep)) {
... fail ...
}
I should perhaps note that in the RFC1982 definition of sequence
space arithmetic, two points that are diametrically opposite on
the circle are not comparable.
Since such ambiguity should be a failure case, a more precisely
correct condition is
Note that this now also includes incep == expi, which should never
be the case for RRSIGs, and so for RRSIG failure makes sense for
both equal and diametrically opposite values. When comparing SOA
serials for AXFR (perhaps not something unbound ever needs to do),
a pair of equal values would of course be treated differently than
a pair or diametrically opposite values.