Maintained by: NLnet Labs

stub-zone unexpected behaviour

Ralph Dolmans
Thu Nov 30 10:03:57 CET 2017


Hi Nick,

It seems that Unbound queries for the nameserver address after it tried
(and failed) to use the glue address. Somehow this query is not send to
the stub address. This looks like a bug. Can you share the Unbound log?
It would be interesting to see the steps Unbound took before sending the
query to the root.

-- Ralph

On 27-11-17 17:06, Nick via Unbound-users wrote:
> Hi Wouter,
> 
> Thanks for your quick response.
> 
> The tests were run using 1.6.4 & 1.6.7. I have just downloaded and built the trunk version (1.6.8), however the behaviour remains the same.
> 
> For me, the second instance of Unbound is required because we would like to dynamically generate the IP of the nameserver, based on the request. My example below is by way of demonstration.
> 
> Any further ideas?
> 
> Thanks again
> 
> Nick
> 
> November 27, 2017 11:07 AM, "W.C.A. Wijngaards via Unbound-users" <unbound-users at unbound.net>
> wrote:
> 
>> Hi Nick,
>>
>> It looks similar to a bug that was fixed (somewhat recently). Try
>> upgrading, perhaps it is simply already solved. It was the failure
>> fallback cases that did not respect configured stub boundaries.
>>
>> If you want unbound to fetch the NS record for a stub from a particular
>> address, there is an option stub-prime: yes for that. And then you
>> don't need that second unbound instance just to serve the NS record.
>>
>> Best regards, Wouter
>>
>> On 24/11/17 17:18, Nick via Unbound-users wrote:
>>
>>> I have configured a stub-zone to delegate requests for a particular
>>> domain (mytest) to another instance of Unbound, which serves the
>>> requests from a Python module (returning an NS record with the
>>> nameserver who can handle the A record request).
>>>
>>> In this particular instance we are testing behaviour when the last DNS
>>> server in the chain is not reachable.
>>>
>>> Heres the flow:
>>>
>>> [local Unbound(172.16.198.20)] -> [mytest Unbound (172.20.0.1)] -> [
>>> unreachable (172.21.0.1) ]
>>>
>>> I use the following command to test:
>>>
>>> #dig -4 @172.16.198.20 mytest.example.mytest
>>>
>>> It works great, when I first start it up - wireshark shows the following
>>> DNS packets:
>>>
>>> 7 3.805095 172.16.198.20 → 172.16.198.20 DNS 94 Standard query 0x4741 A
>>> mytest.example.mytest OPT
>>> 8 3.805328 172.20.0.1 → 172.20.0.1 DNS 94 Standard query 0xbd82 A
>>> mytest.example.mytest OPT
>>> 9 3.805913 172.20.0.1 → 172.20.0.1 DNS 127 Standard query response
>>> 0xbd82 A mytest.example.mytest NS ns.mytest.example.mytest A 172.21.0.1 OPT
>>> 10 3.806112 172.16.198.20 → 172.21.0.1 DNS 94 Standard query 0x5769 A
>>> mytest.example.mytest OPT
>>> 13 4.182941 172.16.198.20 → 172.21.0.1 DNS 94 Standard query 0xa7be A
>>> mytest.example.mytest OPT
>>> 14 4.559900 172.16.198.20 → 172.21.0.1 DNS 94 Standard query 0xafa9 A
>>> mytest.example.mytest OPT
>>> 17 5.313861 172.16.198.20 → 172.21.0.1 DNS 94 Standard query 0x31f7 A
>>> mytest.example.mytest OPT
>>> 20 6.067457 172.16.198.20 → 172.21.0.1 DNS 94 Standard query 0x6245 A
>>> mytest.example.mytest OPT
>>> 21 7.574350 172.16.198.20 → 172.21.0.1 DNS 94 Standard query 0xb9ef A
>>> mytest.example.mytest OPT
>>> 24 9.082170 172.16.198.20 → 172.21.0.1 DNS 94 Standard query 0xe275 A
>>> mytest.example.mytest OPT
>>> 27 12.092103 172.16.198.20 → 172.21.0.1 DNS 94 Standard query 0x9261 A
>>> mytest.example.mytest OPT
>>> 32 15.103658 172.16.198.20 → 172.21.0.1 DNS 83 Standard query 0x4a32 A
>>> mytest.example.mytest
>>> 33 16.106309 172.20.0.1 → 172.20.0.1 DNS 97 Standard query 0x6af6 A
>>> ns.mytest.example.mytest OPT
>>> 34 16.107670 172.20.0.1 → 172.20.0.1 DNS 113 Standard query response
>>> 0x6af6 A ns.mytest.example.mytest A 172.21.0.1 OPT
>>> 35 16.108060 172.16.198.20 → 172.16.198.20 DNS 94 Standard query
>>> response 0x4741 Server failure A mytest.example.mytest OPT
>>> 36 16.108079 172.16.198.20 → 172.16.198.20 ICMP 122 Destination
>>> unreachable (Port unreachable)
>>>
>>> As you can see the 'local' Unbound attempts to query 172.21.0.1 for the
>>> A record. It retries because nothing is listening and eventually give us
>>> a SERVFAIL.
>>>
>>> Now here is the 'strange' thing -
>>>
>>> If I make an initial query for www.google.com, the subsequent behaviour
>>> of the command above changes
>>>
>>> 3 0.000070 172.16.198.20 → 172.16.198.20 DNS 94 Standard query 0x3fac A
>>> mytest.example.mytest OPT
>>> 4 0.000436 172.20.0.1 → 172.20.0.1 DNS 94 Standard query 0xc2af A
>>> mytest.example.mytest OPT
>>> 5 0.001877 172.20.0.1 → 172.20.0.1 DNS 127 Standard query response
>>> 0xc2af A mytest.example.mytest NS ns.mytest.example.mytest A 172.21.0.1 OPT
>>> 6 0.002201 172.16.198.20 → 172.21.0.1 DNS 94 Standard query 0x3bb7 A
>>> mytest.example.mytest OPT
>>> 7 0.378956 172.16.198.20 → 172.21.0.1 DNS 94 Standard query 0x7ab2 A
>>> mytest.example.mytest OPT
>>> 8 0.755943 172.16.198.20 → 172.21.0.1 DNS 94 Standard query 0xef10 A
>>> mytest.example.mytest OPT
>>> 9 1.509470 172.16.198.20 → 172.21.0.1 DNS 94 Standard query 0x2777 A
>>> mytest.example.mytest OPT
>>> 10 2.263616 172.16.198.20 → 172.21.0.1 DNS 94 Standard query 0x0514 A
>>> mytest.example.mytest OPT
>>> 11 3.769610 172.16.198.20 → 172.21.0.1 DNS 94 Standard query 0xc9e9 A
>>> mytest.example.mytest OPT
>>> 14 5.276551 172.16.198.20 → 172.21.0.1 DNS 94 Standard query 0x647c A
>>> mytest.example.mytest OPT
>>> 15 8.288567 172.16.198.20 → 172.21.0.1 DNS 94 Standard query 0x90f2 A
>>> mytest.example.mytest OPT
>>> 16 11.300684 172.16.198.20 → 172.21.0.1 DNS 83 Standard query 0x1e24 A
>>> mytest.example.mytest
>>> *17 12.307535 172.16.198.20 → 193.0.14.129 DNS 97 Standard query 0x704f
>>> A ns.mytest.example.mytest OPT
>>> 18 12.327889 193.0.14.129 → 172.16.198.20 DNS 1082 Standard query
>>> response 0x704f No such name A ns.mytest.example.mytest SOA
>>> a.root-servers.net RRSIG NSEC aaa RRSIG NSEC mz RRSIG OPT*
>>> 19 12.328306 172.16.198.20 → 172.16.198.20 DNS 94 Standard query
>>> response 0x3fac Server failure A mytest.example.mytest OPT
>>> 20 12.328320 172.16.198.20 → 172.16.198.20 ICMP 122 Destination
>>> unreachable (Port unreachable)
>>>
>>> As you can see, even though requests for .mytest should be directed to
>>> 172.20.0.1 (as seen in packet 33 of the first trace) the request for the
>>> ns.mytest.example.mytest in the second trace (packet 17) is sent to one
>>> of the configured root servers.
>>> The net effect is that the client (dig) receives NXDOMAIN, instead of
>>> SERVFAIL.
>>>
>>> Unbound configuration is as follows:
>>>
>>> server:
>>> verbosity:5
>>> do-ip6:no
>>> interface: 172.16.198.20
>>> module-config: "iterator"
>>>
>>> do-ip4: yes
>>> do-udp: yes
>>> do-daemonize: yes
>>> access-control: 172.16.198.0/8 allow
>>> chroot: ""
>>> use-syslog: yes
>>> log-time-ascii: yes
>>> log-queries: yes
>>> local-zone: "mytest" nodefault
>>>
>>> remote-control:
>>> control-interface: 172.16.198.20
>>> control-enable: yes
>>>
>>> stub-zone:
>>> name: "mytest"
>>> stub-addr: 172.20.0.1
>>>
>>> In the logs, the main significant difference I see is a missing
>>> statement in the failed case:
>>>
>>> info: use stub mctest. NS IN
>>>
>>> also all of the root severs are listed as DelegationPoints
>>>
>>> Any help appreciated - perhaps this is a bug?
>>>
>>> Many thanks
>>>
>>> Nick