Bug 3299 - forward CNAME daisy chain is not working
forward CNAME daisy chain is not working
Status: RESOLVED FIXED
Product: unbound
Classification: Unclassified
Component: server
1.6.1
x86_64 OpenBSD
: P5 normal
Assigned To: unbound team
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2017-11-28 17:13 CET by mail
Modified: 2017-11-30 12:18 CET (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description mail 2017-11-28 17:13:21 CET
Hi,

we have a simple internal forwarder entry here:

private-domain: a.b.c
domain-insecure: a.b.c
local-zone: a.b.c typetransparent
forward-zone:
        name: a.b.c
        forward-addr: 1.2.3.4
        forward-addr: 1.2.3.5

1.2.3.4 and 1.2.3.5 are recursive Windows DNS servers.

There is a daisy-chain entry host.a.b.c, which is a CNAME to host.d.e.f which in turn is an A record with IP address.

The zone d.e.f is another internal zone not configured/known to Unbound.

If I query 1.2.3.4 directly I get the IP as result (as expected):

$ nslookup host.a.b.c 1.2.3.4 
Server:         1.2.3.4
Address:        1.2.3.4#53

host.a.b.c     canonical name = host.d.e.f.
Name:   host.d.e.f.
Address: 5.6.7.8

But if I query Unbound I only get the CNAME, but not the A record.

$ dig +short host.a.b.c
host.d.e.f.

From tcpdump we can see that Unbound receives the answer correctly from 
1.2.3.4 containing *both* entries CNAME and A record in the answer.

Why is the A record and IP not returned/ignored/dropped at all by Unbound?

How can change this behaviour? BIND and Windows DNS do return A record 
as well by default.

I found a related bug to qname-minimisation, note we habe it not enabled (default setting).

Some older threads (2008) suggest to add another stub/forwarder for d.e.f. as 
well -- but from what I understand the manpage the forwarding is exactly for
this: let 1.2.3.4 handle the recursion at all and not Unbound attempting 
or dropping anything here.

Thanks,
Regards,
Joerg
Comment 1 Wouter Wijngaards 2017-11-29 09:08:23 CET
Hi Joerg,

You need to change the forward-zone: to stub-zone: in the unbound.conf for a.b.c.

Unbound does not perform cname chases for forward-zone upstreams.  Unbound performs cname chaes for stub-zone upstreams, and this is what you want.

Unbound removes the A record from the reply for security reasons (cache poisoning if you don't).  The CNAME is processed with the configuration options selected, in this case forward-zone (no processing), but if you chose stub-zone, it would have looked for d.e.f.

You could add a stub-zone for name: "d.e.f" with stub-addr: 1.2.3.4 and 1.2.3.5 so that unbound can find the contents of d.e.f.

Best regards, Wouter
Comment 2 mail 2017-11-29 10:26:46 CET
(In reply to Wouter Wijngaards from comment #1)
> Hi Joerg,
> 
> You need to change the forward-zone: to stub-zone: in the unbound.conf for
> a.b.c.
> 
> Unbound does not perform cname chases for forward-zone upstreams.  Unbound
> performs cname chaes for stub-zone upstreams, and this is what you want.

No, I want 1.2.3.4 to do the recursive lookup, and it actually does correctly,
but Unbound does ignore it.

> Unbound removes the A record from the reply for security reasons (cache
> poisoning if you don't).  

Ok, I see, so this is by design and wanted. But then this should be really
mentioned in the man page forward section. For example, maybe something like 
this should be added: 

"[...] unbound does not perform recursion itself for the forward zone, 
it lets the remote server do it.
Note: Due to secruity reasons unbound may drop returned A records 
for CNAME dasiy-chains.  Stub-Zones which let unbound handle the lookup
itself are preferred in such cases."

> The CNAME is processed with the configuration
> options selected, in this case forward-zone (no processing), but if you
> chose stub-zone, it would have looked for d.e.f.

I know.

> You could add a stub-zone for name: "d.e.f" with stub-addr: 1.2.3.4 and
> 1.2.3.5 so that unbound can find the contents of d.e.f.

That is what I actually wanted to avoid by using forwarding instead of (additional) stubs, who knows which other CNAMEs to further internal 
subdomains are added by 1.2.3.4 admins in future?!

I just expected what man-page said: "it lets the remote server do it."
But I'm fine and can live with this behaviour, if this is mentioned in 
documentation. 

Nevertheless, may I suggest a little knob "insecure-forward" or something,
which returns the A record to mimic BIND and Windows DNS behavior
and makes migrations easier?

Thanks,
Regards,
Joerg
Comment 3 Wouter Wijngaards 2017-11-29 10:39:21 CET
Hi Joerg,

If unbound cannot look up the target of the CNAME, then it is incorrect content.  I mean, that it is content that does not exist.  According to the view of unbound.

Did you know that (newer) unbound has view support for having names that have different content (for such migrations).  The views can have localdata in them.

I think you want to configure unbound to serve different content for a name depending on how it is queried for.  Unbound does not support that.  Apart from the view configuration options.  And that is what I think you need.

Well if 1.2.3.4 adds any other contens, in effect they are authoritative for '.', everything.  You could try to list the 'c' and 'f' as places where unbound starts looking for 1.2.3.4 to give the answer.  They can then add new b1.c, b2.c, b3.c contents as they want to.

I don't really want to add the option you suggest because the cache would become incoherent, with different content for the same lookup key; that A record.  Currently, the views setup is meant to have options (also new options for) this kind of setup.

Best regards, Wouter
Comment 4 mail 2017-11-29 18:33:12 CET
(In reply to Wouter Wijngaards from comment #3)
> Hi Joerg,
> 
> If unbound cannot look up the target of the CNAME, then it is incorrect
> content.  I mean, that it is content that does not exist.  According to the
> view of unbound.

I understand that and it makes sense to me. 

> Did you know that (newer) unbound has view support for having names that
> have different content (for such migrations).  The views can have localdata
> in them.
> 
> I think you want to configure unbound to serve different content for a name
> depending on how it is queried for.  Unbound does not support that.  Apart
> from the view configuration options.  And that is what I think you need.

I don't think that views will help me here, since I'm not in control of 
1.2.3.4 or what it returns exactly, despite these are all internal-only 
things. 
But no matter, I can cope with this.

> I don't really want to add the option you suggest because the cache would
> become incoherent, with different content for the same lookup key; that A
> record.  Currently, the views setup is meant to have options (also new
> options for) this kind of setup.

Fine with me. 

But as suggested earlier: please adjust the man page and add a short notice, 
one or two sentences in forward section to document that security behavior.

My colleagues and me really struggeled on the current man page sentence:
"...it lets the remote server do it." and expected different behaviour from it.

Thanks for elaborations!
Comment 5 Wouter Wijngaards 2017-11-30 09:35:30 CET
Hi Joerg,

These lines have been added to unbound.conf.5:

CNAMEs are chased by unbound itself, asking the remote server for every
name in the indirection chain, to protect the local cache from illegal
indirect referenced items.

Thanks for the followup and fix suggestion.

Sorry I cannot fix this for you.  I would have hoped views would have been useful, because they are meant to be useful for migration situations.

Best regards, Wouter
Comment 6 mail 2017-11-30 12:18:39 CET
(In reply to Wouter Wijngaards from comment #5)
>
> These lines have been added to unbound.conf.5:
>
> CNAMEs are chased by unbound itself, asking the remote server for every
> name in the indirection chain, to protect the local cache from illegal
> indirect referenced items.

Thanks!