Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

resolved stub resolver doesn't provide RRSIG data in replies when DO/CD queries are sent to it #4621

Closed
2 tasks done
wtoorop opened this issue Nov 8, 2016 · 23 comments
Closed
2 tasks done
Labels
dnssec resolve RFE 🎁 Request for Enhancement, i.e. a feature request

Comments

@wtoorop
Copy link

wtoorop commented Nov 8, 2016

Submission type

  • Bug report
  • Request for enhancement (RFE)

systemd version the issue has been seen with

231-9git1? (the one that ships with ubuntu 16.10)

Used distribution

Ubuntu

In case of bug report: Expected behaviour you didn't see

When sending the DO bit in queries to 127.0.0.53, the returned data did not include DNSSEC data (i.e. the RRSIGs).
When asking for non-existent records, the DNSSEC proof of non-existance is missing.

In case of bug report: Unexpected behaviour you saw

When asking for non-existent records, the AD bit is also not set, as if systemd-resolved did not validate the non-existance of the requested record.

In case of bug report: Steps to reproduce the problem

> $ dig @127.0.0.53 nlnetlabs.nl +dnssec

; <<>> DiG 9.10.3-P4-Ubuntu <<>> @127.0.0.53 nlnetlabs.nl +dnssec
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 54947
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 65494
;; QUESTION SECTION:
;nlnetlabs.nl.			IN	A

;; ANSWER SECTION:
nlnetlabs.nl.		5332	IN	A	185.49.140.10

;; Query time: 0 msec
;; SERVER: 127.0.0.53#53(127.0.0.53)
;; WHEN: Tue Nov 08 15:29:19 CET 2016
;; MSG SIZE  rcvd: 57

$ dig @127.0.0.53 nonexistant.nlnetlabs.nl +dnssec

; <<>> DiG 9.10.3-P4-Ubuntu <<>> @127.0.0.53 nonexistant.nlnetlabs.nl +dnssec
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 3445
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 65494
;; QUESTION SECTION:
;nonexistant.nlnetlabs.nl.	IN	A

;; Query time: 3 msec
;; SERVER: 127.0.0.53#53(127.0.0.53)
;; WHEN: Tue Nov 08 15:29:43 CET 2016
;; MSG SIZE  rcvd: 53
@wtoorop
Copy link
Author

wtoorop commented Nov 8, 2016

But besides the bug report... thanks for bringing DNSSEC so close to the end-user!

@poettering
Copy link
Member

Well, resolved is not supposed to be a DNS server, it's supposed to be exactly good enough so that libc-like DNS clients can resolve their stuff, and we carry enough info for the AD bit to be set. That's by design really. See the commit msg of b30bf55.

If we don't set AD properly for negative replies, that'd be a bug however, indeed.

@poettering poettering changed the title [systemd-resolved] 127.0.0.53 server strips DNSSEC resolved doesn't set AD properly for negative replies on stub listener Nov 11, 2016
@poettering poettering added this to the v233 milestone Nov 11, 2016
@wtoorop
Copy link
Author

wtoorop commented Nov 12, 2016

Op 12-11-16 om 05:37 schreef Lennart Poettering:

Well, resolved is not supposed to be a DNS server, it's supposed to be
exactly good enough so that libc-like DNS clients can resolve their
stuff, and we carry enough info for the AD bit to be set.

Thanks Lennart. I understand systemd-resolved is not a fully fledged
DNS server (but a DNS interface on a stub resolver), but signatures
alongside the requested RRs would be good for applications that lookup
TLSA records (or SSHFP or other DANE like RRs) and confirm the validity
(or check the non-existance proof) themselves.

ldns and getdns can do this for example.

Perhaps this could be a enhancement request then?
Do you want me to put it in a separate issue?

Also, I have to admit that I cannot find it specified in the RFCs right
now, but it is conventional to return the DNSSEC data when the DO bit is
set. Returning only AD bit and not the signatures, NSEC's etc. is
normally done when you send a query with the AD bit set. Quote from
RFC6840 section 5.7 (last sentence implies DNSSEC data is requested with
the DO bit):

5.7. Setting the AD Bit on Queries

The semantics of the Authentic Data (AD) bit in the query were
previously undefined. Section 4.6 of [RFC4035] instructed resolvers
to always clear the AD bit when composing queries.

This document defines setting the AD bit in a query as a signal
indicating that the requester understands and is interested in the
value of the AD bit in the response. This allows a requester to
indicate that it understands the AD bit without also requesting
DNSSEC data via the DO bit.

@poettering
Copy link
Member

well, if clients want to validate DNSSEC on their own, they should probably not involve resolved then I think...

But anyway, I'll turn this into an RFE, but I don't think this is really in focus for us.

@poettering poettering added the RFE 🎁 Request for Enhancement, i.e. a feature request label Nov 14, 2016
@poettering poettering changed the title resolved doesn't set AD properly for negative replies on stub listener resolved stub resolver doesn't provide RRSIG data in replies when DO/CD queries are sent to it Nov 14, 2016
@poettering poettering modified the milestone: v233 Nov 18, 2016
@alexanderkjall
Copy link

Hi, I'm not sure if I'm seeing the same issue, or at least a variant of the same issue.

I configured my system (ubuntu 16.10) to use systemd as the dns resolver, and that broke lookups of RRSIG records.

If i try to use dig i get this result:

$ dig +dnssec xil.se RRSIG

; <<>> DiG 9.10.3-P4-Ubuntu <<>> +dnssec xil.se RRSIG
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: FORMERR, id: 14901
;; flags: qr rd ra; QUERY: 0, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0

;; WARNING: EDNS query returned status FORMERR - retry with '+nodnssec +noedns'

;; Query time: 0 msec
;; SERVER: 127.0.0.53#53(127.0.0.53)
;; WHEN: Sat Nov 19 17:51:55 CET 2016
;; MSG SIZE  rcvd: 12


and by using systemd-resolve directly i get this result:

$ systemd-resolve -t RRSIG xil.se
xil.se: resolve call failed: Specified resource record type 46 may not be used in a query.

@andersk
Copy link

andersk commented Dec 4, 2016

well, if clients want to validate DNSSEC on their own, they should probably not involve resolved then I think...

If /etc/resolv.conf points to 127.0.0.53, what choice do they have?

poettering added a commit to poettering/systemd that referenced this issue Feb 15, 2017
When we managed to prove non-existance of a name, then we should
properly propagate this to clients by setting the AD bit on NXDOMAIN.

See: systemd#4621
@poettering
Copy link
Member

If we don't set AD properly for negative replies, that'd be a bug however, indeed.

This bit should be fixed now with #5347. Dropping the v233 milestone hence, as what remains of this issue is mostly RFE.

@poettering poettering removed this from the v233 milestone Feb 15, 2017
poettering added a commit to poettering/systemd that referenced this issue Feb 17, 2017
When we managed to prove non-existance of a name, then we should
properly propagate this to clients by setting the AD bit on NXDOMAIN.

See: systemd#4621
@traud
Copy link

traud commented May 14, 2018

Please, help! Or in other words, I would like to have an answer to Anders’ question above. My very own app which does DANE, broke on Ubuntu 18.04 LTS. It worked great in Ubuntu 14.04 LTS and Ubuntu 16.04 LTS. This is a software bug for sure. Now, I have to report this somewhere, even if it is to myself.

A) Ubuntu
uses systemd-resolved on default and puts it in /etc/resolv.conf. In my case, just 127.0.0.53 is listed in that file. This is since Ubuntu 17.04, actually.

B) systemd-resolved
does not provide RRSIG. Therefore, the official example code gives:

Result is bogus: validation failure <www.nlnetlabs.nl. A IN>: no DNSKEY rrset for trust anchor . while building chain of trust.

C) Unbound
state in their example code, /etc/resolv.conf can be used for caching and when you trust that file/server. In former days, one did sudo apt install unbound which installed a DNS resolver at 127.0.0.1 and that creates a /etc/resolv.conf with just 127.0.0.1. Since Ubuntu 18.04 LTS this does not help, because systemd-resolved is still the only DNS server listed in /etc/resolv.conf after installing Unbound. Is this an issue of the package or just the tutorial?

D) Myself
Did I misunderstood that example code and my code should change:

  • Should I test for /run/systemd/resolve/stub-resolv.conf, avoid /etc/resolv.conf, and use Unbound in full-resolver mode (without caching). Or
  • Instead of /etc/resolv.conf, first I try ub_ctx_resolvconf(ctx, "/run/systemd/resolve/resolv.conf"). That is not encouraged by the man page…

E) End-Users
Or is this no bug at all, and an interested user should be educated to change the symbolic link of /etc/resolv.conf to /run/systemd/resolve/resolv.conf?


Another example
$ dig www.nlnetlabs.nl. A +dnssec
This does not give RRSIG on Ubuntu 18.04 LTS because resolved does not provide this feature. This worked in Ubuntu 16.04 LTS and earlier because my upstream DNS server provides DNSSEC caching.

$ dig @127.0.0.1 www.nlnetlabs.nl. A +dnssec
This approach works, after sudo apt install unbound. Therefore, another approach for my source code would be ub_ctx_set_fwd(ctx, "127.0.0.1").

$ dig @8.8.8.8 www.nlnetlabs.nl. A +dnssec
This approach—the DNS servers from Google—works always, of course.


Yet another example
With the tools from the package hash-slinger, I have to specify --resolvconf "/run/systemd/resolve/resolv.conf" to overwrite the default of /etc/resolv.conf. Otherwise, I get error messages like

Unsuccessful lookup or no data returned for OPENPGPKEY (rrtype 61)


There must be a totally easy answer, which I do not see. My app does not work on default in Ubuntu 18.04 LTS at all, because the DNS result is even ‘bogus’. Please, help!

I cross-posted this on the Unbound mailing-list…

@sidusnare
Copy link

If this is not a DNS server, perhaps we shouldn't use it as the default DNS server?

@traud
Copy link

traud commented Jul 5, 2018

Has anyone an idea where to report my bug: Is it A, B, C, D, or E? As explained on the Unbound mailing list, I found another workaround for Ubuntu 18.04 LTS: sudo apt install unbound resolvconf

@chrwei
Copy link

chrwei commented Dec 27, 2018

the work-around is easy, just specify the real dns server on your diag tools. this forces you to check what server resolved is actually using first, which is simple: systemd-resolve --status

@detly
Copy link

detly commented Dec 27, 2018

@traud I don't know the official answer, but I did (A). https://bugs.launchpad.net/ubuntu/+source/systemd/+bug/1782679

@exploide
Copy link
Contributor

According to the BIND docs, the tool delv is the designated successor of dig, with better DNSSEC support built-in.

I stumbled over this issue here because I was wondering and debugging why delv was no longer able to resolve DNS names.

$ delv iana.org
;; no valid RRSIG resolving 'org/DS/IN': 127.0.0.53#53
;; no valid DS resolving 'iana.org/A/IN': 127.0.0.53#53
;; resolution failed: no valid DS

It's because systemd-resolved is used and RRSIG records are not passed through.

Of course, one can always manually tell delv to use @another-resolver but I think stuff should be functional by default and don't break standard tasks. Hence, it would be great if resolved could deliver also DNSSEC related records.

@msva
Copy link

msva commented Dec 21, 2019

@poettering I think, "resolved is not supposed to be a real DNS server" answer can't be counted as valid in context of DNSSEC support requests.

For now, using systemd's "stub" resolver is the only way on linux systems to have link-aware DNS resolver (like, say, MacOS have long time ago).
I mean, when we have multiple links, all of them are DHCP-enabled, and all of them sends different "search" domains, say "zone1", "zone2", and "zone3" respectively.
Using sysD's stub resolver, there is expected logic: if we're trying resolve host.zone1 - request goes to link1's resolvers, host.zone2 - to link2's and so on.

Unfortunately, there is absolutely no way to have this logic out-of-the-box, without tons of magic (like auto-regeneration of dnsmasq/bind configs triggered by network status change), which is definitely not a way to go for typical user.

Talking that, for now, almost all of the linux distros moved to systemd-resolved's stub resolver as default system resolver, so, now it is de-facto standard for linux system (whatever it will be: desktop, server or "new generation of embedded" (arm/mips/risc-v powered by ubuntu/debian/fedora).
Wasn't that the goal of SystemD?

And all of that people, who use that systems, DO need full DNSSEC support in their systems, but not just "stub-resolver will internally validate the answer (and will fail to resolve on MITM), but won't let you get the signatures".

And, as already mentioned, current behavior also brakes network diagnostic tools like dig...

So, just as all the people above, I signing on the "petition" to SystemD developers to fully implement DNSSEC in stub resolver, starting with DO support.

@msva
Copy link

msva commented Dec 21, 2019

// well, that situation with "broken DNSSEC compatibility everywhere" is one of the reasons why such monsters as DNS-over-HTTP(S) was created and gains their popularity :-/

@pemensik
Copy link
Collaborator

pemensik commented Oct 5, 2020

Its been four years, any progress?

poettering added a commit to poettering/systemd that referenced this issue Nov 19, 2020
This substantially beefs up the local DNS stub feature set in order to
allow local clients to do DNSSEC validation through the stub.

Previously we'd return NOTIMP if we'd get a DO or DO+CD lookup. With
this change we'll instead:

1. If we get DO+CD requests (i.e. DNSSEC with no local checking) we'll
   proxy DNS queries and response mostly unmodified to/from upstream DNS
   servers if possible (this is called "bypass" mode).  We will patch in
   new request IDs, (and patch them back out on reply), so that we can
   sanely keep track of things.  We'll also maintain a minimal local
   cache for such lookups, always keeping the whole DNS packets in it
   (if we reply from cache we'll patch the TTLs of all included RRs).

2. If we get DO requests without CD (i.e. DNSSEC with local checking)
   we'll resolve and validate locally. In this mode we will not proxy
   packets, but generate our own. We will however cache the combination
   of answer RRs (along with their packet section assignments) we got
   back in the cache, and use this information to generate reply packets
   from the DNS stub.

In both cases: if we determine a lookup is to be answered from LLMNR or
mDNS we'll always revert to non-DNSSEC, non-proxy operation as before.
Answers will lack the DO bit then, since the data cannot be validated
via DNSSEC by the clients.

To make this logic more debuggable, this also adds query flags for
turning off RR sources. i.e. cache/network/zone/trust anchor/local
synthesis may now be disabled individually for each lookup.

The cache is substantially updated to make all this work: in addition to
caching simple RRs for lookup RR keys, we'll now cache the whole packets
and the whole combination of RRs, so that we can answer DO and DO+CD
replies sensibly according to the rules described above. This sounds
wasteful, but given that the
DnsResourceRecord/DnsResourceKey/DnsAnswer/DnsPacket
objects are all ref-counted and we try to merge references the actual
additional memory used should be limited (but this might be something to
optimize further later on).

To implement classic RR key lookups and new-style packet proxy lookups
(i.e. the ones necessary for DO+CD packet proxying, as described above)
DnsTransaction and DnsQuery objects now always maintain either a
DnsResourceKey/DnsQuestion as lookup key or a DnsPacket for "bypass"
mode.

Fixes: systemd#4621 systemd#17218
poettering added a commit to poettering/systemd that referenced this issue Nov 20, 2020
This substantially beefs up the local DNS stub feature set in order to
allow local clients to do DNSSEC validation through the stub.

Previously we'd return NOTIMP if we'd get a DO or DO+CD lookup. With
this change we'll instead:

1. If we get DO+CD requests (i.e. DNSSEC with no local checking) we'll
   proxy DNS queries and response mostly unmodified to/from upstream DNS
   servers if possible (this is called "bypass" mode).  We will patch in
   new request IDs, (and patch them back out on reply), so that we can
   sanely keep track of things.  We'll also maintain a minimal local
   cache for such lookups, always keeping the whole DNS packets in it
   (if we reply from cache we'll patch the TTLs of all included RRs).

2. If we get DO requests without CD (i.e. DNSSEC with local checking)
   we'll resolve and validate locally. In this mode we will not proxy
   packets, but generate our own. We will however cache the combination
   of answer RRs (along with their packet section assignments) we got
   back in the cache, and use this information to generate reply packets
   from the DNS stub.

In both cases: if we determine a lookup is to be answered from LLMNR or
mDNS we'll always revert to non-DNSSEC, non-proxy operation as before.
Answers will lack the DO bit then, since the data cannot be validated
via DNSSEC by the clients.

To make this logic more debuggable, this also adds query flags for
turning off RR sources. i.e. cache/network/zone/trust anchor/local
synthesis may now be disabled individually for each lookup.

The cache is substantially updated to make all this work: in addition to
caching simple RRs for lookup RR keys, we'll now cache the whole packets
and the whole combination of RRs, so that we can answer DO and DO+CD
replies sensibly according to the rules described above. This sounds
wasteful, but given that the
DnsResourceRecord/DnsResourceKey/DnsAnswer/DnsPacket
objects are all ref-counted and we try to merge references the actual
additional memory used should be limited (but this might be something to
optimize further later on).

To implement classic RR key lookups and new-style packet proxy lookups
(i.e. the ones necessary for DO+CD packet proxying, as described above)
DnsTransaction and DnsQuery objects now always maintain either a
DnsResourceKey/DnsQuestion as lookup key or a DnsPacket for "bypass"
mode.

Fixes: systemd#4621 systemd#17218
poettering added a commit to poettering/systemd that referenced this issue Dec 2, 2020
This substantially beefs up the local DNS stub feature set in order to
allow local clients to do DNSSEC validation through the stub.

Previously we'd return NOTIMP if we'd get a DO or DO+CD lookup. With
this change we'll instead:

1. If we get DO+CD requests (i.e. DNSSEC with no local checking) we'll
   proxy DNS queries and response mostly unmodified to/from upstream DNS
   servers if possible (this is called "bypass" mode).  We will patch in
   new request IDs, (and patch them back out on reply), so that we can
   sanely keep track of things.  We'll also maintain a minimal local
   cache for such lookups, always keeping the whole DNS packets in it
   (if we reply from cache we'll patch the TTLs of all included RRs).

2. If we get DO requests without CD (i.e. DNSSEC with local checking)
   we'll resolve and validate locally. In this mode we will not proxy
   packets, but generate our own. We will however cache the combination
   of answer RRs (along with their packet section assignments) we got
   back in the cache, and use this information to generate reply packets
   from the DNS stub.

In both cases: if we determine a lookup is to be answered from LLMNR or
mDNS we'll always revert to non-DNSSEC, non-proxy operation as before.
Answers will lack the DO bit then, since the data cannot be validated
via DNSSEC by the clients.

To make this logic more debuggable, this also adds query flags for
turning off RR sources. i.e. cache/network/zone/trust anchor/local
synthesis may now be disabled individually for each lookup.

The cache is substantially updated to make all this work: in addition to
caching simple RRs for lookup RR keys, we'll now cache the whole packets
and the whole combination of RRs, so that we can answer DO and DO+CD
replies sensibly according to the rules described above. This sounds
wasteful, but given that the
DnsResourceRecord/DnsResourceKey/DnsAnswer/DnsPacket
objects are all ref-counted and we try to merge references the actual
additional memory used should be limited (but this might be something to
optimize further later on).

To implement classic RR key lookups and new-style packet proxy lookups
(i.e. the ones necessary for DO+CD packet proxying, as described above)
DnsTransaction and DnsQuery objects now always maintain either a
DnsResourceKey/DnsQuestion as lookup key or a DnsPacket for "bypass"
mode.

Fixes: systemd#4621 systemd#17218
poettering added a commit to poettering/systemd that referenced this issue Dec 2, 2020
This substantially beefs up the local DNS stub feature set in order to
allow local clients to do DNSSEC validation through the stub.

Previously we'd return NOTIMP if we'd get a DO or DO+CD lookup. With
this change we'll instead:

1. If we get DO+CD requests (i.e. DNSSEC with no local checking) we'll
   proxy DNS queries and response mostly unmodified to/from upstream DNS
   servers if possible (this is called "bypass" mode).  We will patch in
   new request IDs, (and patch them back out on reply), so that we can
   sanely keep track of things.  We'll also maintain a minimal local
   cache for such lookups, always keeping the whole DNS packets in it
   (if we reply from cache we'll patch the TTLs of all included RRs).

2. If we get DO requests without CD (i.e. DNSSEC with local checking)
   we'll resolve and validate locally. In this mode we will not proxy
   packets, but generate our own. We will however cache the combination
   of answer RRs (along with their packet section assignments) we got
   back in the cache, and use this information to generate reply packets
   from the DNS stub.

In both cases: if we determine a lookup is to be answered from LLMNR or
mDNS we'll always revert to non-DNSSEC, non-proxy operation as before.
Answers will lack the DO bit then, since the data cannot be validated
via DNSSEC by the clients.

To make this logic more debuggable, this also adds query flags for
turning off RR sources. i.e. cache/network/zone/trust anchor/local
synthesis may now be disabled individually for each lookup.

The cache is substantially updated to make all this work: in addition to
caching simple RRs for lookup RR keys, we'll now cache the whole packets
and the whole combination of RRs, so that we can answer DO and DO+CD
replies sensibly according to the rules described above. This sounds
wasteful, but given that the
DnsResourceRecord/DnsResourceKey/DnsAnswer/DnsPacket
objects are all ref-counted and we try to merge references the actual
additional memory used should be limited (but this might be something to
optimize further later on).

To implement classic RR key lookups and new-style packet proxy lookups
(i.e. the ones necessary for DO+CD packet proxying, as described above)
DnsTransaction and DnsQuery objects now always maintain either a
DnsResourceKey/DnsQuestion as lookup key or a DnsPacket for "bypass"
mode.

Fixes: systemd#4621 systemd#17218
poettering added a commit to poettering/systemd that referenced this issue Dec 3, 2020
This substantially beefs up the local DNS stub feature set in order to
allow local clients to do DNSSEC validation through the stub.

Previously we'd return NOTIMP if we'd get a DO or DO+CD lookup. With
this change we'll instead:

1. If we get DO+CD requests (i.e. DNSSEC with no local checking) we'll
   proxy DNS queries and response mostly unmodified to/from upstream DNS
   servers if possible (this is called "bypass" mode).  We will patch in
   new request IDs, (and patch them back out on reply), so that we can
   sanely keep track of things.  We'll also maintain a minimal local
   cache for such lookups, always keeping the whole DNS packets in it
   (if we reply from cache we'll patch the TTLs of all included RRs).

2. If we get DO requests without CD (i.e. DNSSEC with local checking)
   we'll resolve and validate locally. In this mode we will not proxy
   packets, but generate our own. We will however cache the combination
   of answer RRs (along with their packet section assignments) we got
   back in the cache, and use this information to generate reply packets
   from the DNS stub.

In both cases: if we determine a lookup is to be answered from LLMNR or
mDNS we'll always revert to non-DNSSEC, non-proxy operation as before.
Answers will lack the DO bit then, since the data cannot be validated
via DNSSEC by the clients.

To make this logic more debuggable, this also adds query flags for
turning off RR sources. i.e. cache/network/zone/trust anchor/local
synthesis may now be disabled individually for each lookup.

The cache is substantially updated to make all this work: in addition to
caching simple RRs for lookup RR keys, we'll now cache the whole packets
and the whole combination of RRs, so that we can answer DO and DO+CD
replies sensibly according to the rules described above. This sounds
wasteful, but given that the
DnsResourceRecord/DnsResourceKey/DnsAnswer/DnsPacket
objects are all ref-counted and we try to merge references the actual
additional memory used should be limited (but this might be something to
optimize further later on).

To implement classic RR key lookups and new-style packet proxy lookups
(i.e. the ones necessary for DO+CD packet proxying, as described above)
DnsTransaction and DnsQuery objects now always maintain either a
DnsResourceKey/DnsQuestion as lookup key or a DnsPacket for "bypass"
mode.

Fixes: systemd#4621 systemd#17218
poettering added a commit to poettering/systemd that referenced this issue Dec 4, 2020
This substantially beefs up the local DNS stub feature set in order to
allow local clients to do DNSSEC validation through the stub.

Previously we'd return NOTIMP if we'd get a DO or DO+CD lookup. With
this change we'll instead:

1. If we get DO+CD requests (i.e. DNSSEC with no local checking) we'll
   proxy DNS queries and response mostly unmodified to/from upstream DNS
   servers if possible (this is called "bypass" mode).  We will patch in
   new request IDs, (and patch them back out on reply), so that we can
   sanely keep track of things.  We'll also maintain a minimal local
   cache for such lookups, always keeping the whole DNS packets in it
   (if we reply from cache we'll patch the TTLs of all included RRs).

2. If we get DO requests without CD (i.e. DNSSEC with local checking)
   we'll resolve and validate locally. In this mode we will not proxy
   packets, but generate our own. We will however cache the combination
   of answer RRs (along with their packet section assignments) we got
   back in the cache, and use this information to generate reply packets
   from the DNS stub.

In both cases: if we determine a lookup is to be answered from LLMNR or
mDNS we'll always revert to non-DNSSEC, non-proxy operation as before.
Answers will lack the DO bit then, since the data cannot be validated
via DNSSEC by the clients.

To make this logic more debuggable, this also adds query flags for
turning off RR sources. i.e. cache/network/zone/trust anchor/local
synthesis may now be disabled individually for each lookup.

The cache is substantially updated to make all this work: in addition to
caching simple RRs for lookup RR keys, we'll now cache the whole packets
and the whole combination of RRs, so that we can answer DO and DO+CD
replies sensibly according to the rules described above. This sounds
wasteful, but given that the
DnsResourceRecord/DnsResourceKey/DnsAnswer/DnsPacket
objects are all ref-counted and we try to merge references the actual
additional memory used should be limited (but this might be something to
optimize further later on).

To implement classic RR key lookups and new-style packet proxy lookups
(i.e. the ones necessary for DO+CD packet proxying, as described above)
DnsTransaction and DnsQuery objects now always maintain either a
DnsResourceKey/DnsQuestion as lookup key or a DnsPacket for "bypass"
mode.

Fixes: systemd#4621 systemd#17218
poettering added a commit to poettering/systemd that referenced this issue Dec 7, 2020
This substantially beefs up the local DNS stub feature set in order to
allow local clients to do DNSSEC validation through the stub.

Previously we'd return NOTIMP if we'd get a DO or DO+CD lookup. With
this change we'll instead:

1. If we get DO+CD requests (i.e. DNSSEC with no local checking) we'll
   proxy DNS queries and response mostly unmodified to/from upstream DNS
   servers if possible (this is called "bypass" mode).  We will patch in
   new request IDs, (and patch them back out on reply), so that we can
   sanely keep track of things.  We'll also maintain a minimal local
   cache for such lookups, always keeping the whole DNS packets in it
   (if we reply from cache we'll patch the TTLs of all included RRs).

2. If we get DO requests without CD (i.e. DNSSEC with local checking)
   we'll resolve and validate locally. In this mode we will not proxy
   packets, but generate our own. We will however cache the combination
   of answer RRs (along with their packet section assignments) we got
   back in the cache, and use this information to generate reply packets
   from the DNS stub.

In both cases: if we determine a lookup is to be answered from LLMNR or
mDNS we'll always revert to non-DNSSEC, non-proxy operation as before.
Answers will lack the DO bit then, since the data cannot be validated
via DNSSEC by the clients.

To make this logic more debuggable, this also adds query flags for
turning off RR sources. i.e. cache/network/zone/trust anchor/local
synthesis may now be disabled individually for each lookup.

The cache is substantially updated to make all this work: in addition to
caching simple RRs for lookup RR keys, we'll now cache the whole packets
and the whole combination of RRs, so that we can answer DO and DO+CD
replies sensibly according to the rules described above. This sounds
wasteful, but given that the
DnsResourceRecord/DnsResourceKey/DnsAnswer/DnsPacket
objects are all ref-counted and we try to merge references the actual
additional memory used should be limited (but this might be something to
optimize further later on).

To implement classic RR key lookups and new-style packet proxy lookups
(i.e. the ones necessary for DO+CD packet proxying, as described above)
DnsTransaction and DnsQuery objects now always maintain either a
DnsResourceKey/DnsQuestion as lookup key or a DnsPacket for "bypass"
mode.

Fixes: systemd#4621 systemd#17218
poettering added a commit to poettering/systemd that referenced this issue Dec 7, 2020
This substantially beefs up the local DNS stub feature set in order to
allow local clients to do DNSSEC validation through the stub.

Previously we'd return NOTIMP if we'd get a DO or DO+CD lookup. With
this change we'll instead:

1. If we get DO+CD requests (i.e. DNSSEC with no local checking) we'll
   proxy DNS queries and response mostly unmodified to/from upstream DNS
   servers if possible (this is called "bypass" mode).  We will patch in
   new request IDs, (and patch them back out on reply), so that we can
   sanely keep track of things.  We'll also maintain a minimal local
   cache for such lookups, always keeping the whole DNS packets in it
   (if we reply from cache we'll patch the TTLs of all included RRs).

2. If we get DO requests without CD (i.e. DNSSEC with local checking)
   we'll resolve and validate locally. In this mode we will not proxy
   packets, but generate our own. We will however cache the combination
   of answer RRs (along with their packet section assignments) we got
   back in the cache, and use this information to generate reply packets
   from the DNS stub.

In both cases: if we determine a lookup is to be answered from LLMNR or
mDNS we'll always revert to non-DNSSEC, non-proxy operation as before.
Answers will lack the DO bit then, since the data cannot be validated
via DNSSEC by the clients.

To make this logic more debuggable, this also adds query flags for
turning off RR sources. i.e. cache/network/zone/trust anchor/local
synthesis may now be disabled individually for each lookup.

The cache is substantially updated to make all this work: in addition to
caching simple RRs for lookup RR keys, we'll now cache the whole packets
and the whole combination of RRs, so that we can answer DO and DO+CD
replies sensibly according to the rules described above. This sounds
wasteful, but given that the
DnsResourceRecord/DnsResourceKey/DnsAnswer/DnsPacket
objects are all ref-counted and we try to merge references the actual
additional memory used should be limited (but this might be something to
optimize further later on).

To implement classic RR key lookups and new-style packet proxy lookups
(i.e. the ones necessary for DO+CD packet proxying, as described above)
DnsTransaction and DnsQuery objects now always maintain either a
DnsResourceKey/DnsQuestion as lookup key or a DnsPacket for "bypass"
mode.

Fixes: systemd#4621 systemd#17218
poettering added a commit to poettering/systemd that referenced this issue Jan 19, 2021
This substantially beefs up the local DNS stub feature set in order to
allow local clients to do DNSSEC validation through the stub.

Previously we'd return NOTIMP if we'd get a DO or DO+CD lookup. With
this change we'll instead:

1. If we get DO+CD requests (i.e. DNSSEC with no local checking) we'll
   proxy DNS queries and response mostly unmodified to/from upstream DNS
   servers if possible (this is called "bypass" mode).  We will patch in
   new request IDs, (and patch them back out on reply), so that we can
   sanely keep track of things.  We'll also maintain a minimal local
   cache for such lookups, always keeping the whole DNS packets in it
   (if we reply from cache we'll patch the TTLs of all included RRs).

2. If we get DO requests without CD (i.e. DNSSEC with local checking)
   we'll resolve and validate locally. In this mode we will not proxy
   packets, but generate our own. We will however cache the combination
   of answer RRs (along with their packet section assignments) we got
   back in the cache, and use this information to generate reply packets
   from the DNS stub.

In both cases: if we determine a lookup is to be answered from LLMNR or
mDNS we'll always revert to non-DNSSEC, non-proxy operation as before.
Answers will lack the DO bit then, since the data cannot be validated
via DNSSEC by the clients.

To make this logic more debuggable, this also adds query flags for
turning off RR sources. i.e. cache/network/zone/trust anchor/local
synthesis may now be disabled individually for each lookup.

The cache is substantially updated to make all this work: in addition to
caching simple RRs for lookup RR keys, we'll now cache the whole packets
and the whole combination of RRs, so that we can answer DO and DO+CD
replies sensibly according to the rules described above. This sounds
wasteful, but given that the
DnsResourceRecord/DnsResourceKey/DnsAnswer/DnsPacket
objects are all ref-counted and we try to merge references the actual
additional memory used should be limited (but this might be something to
optimize further later on).

To implement classic RR key lookups and new-style packet proxy lookups
(i.e. the ones necessary for DO+CD packet proxying, as described above)
DnsTransaction and DnsQuery objects now always maintain either a
DnsResourceKey/DnsQuestion as lookup key or a DnsPacket for "bypass"
mode.

Fixes: systemd#4621 systemd#17218
poettering added a commit to poettering/systemd that referenced this issue Feb 5, 2021
This substantially beefs up the local DNS stub feature set in order to
allow local clients to do DNSSEC validation through the stub.

Previously we'd return NOTIMP if we'd get a DO or DO+CD lookup. With
this change we'll instead:

1. If we get DO+CD requests (i.e. DNSSEC with no local checking) we'll
   proxy DNS queries and response mostly unmodified to/from upstream DNS
   servers if possible (this is called "bypass" mode).  We will patch in
   new request IDs, (and patch them back out on reply), so that we can
   sanely keep track of things.  We'll also maintain a minimal local
   cache for such lookups, always keeping the whole DNS packets in it
   (if we reply from cache we'll patch the TTLs of all included RRs).

2. If we get DO requests without CD (i.e. DNSSEC with local checking)
   we'll resolve and validate locally. In this mode we will not proxy
   packets, but generate our own. We will however cache the combination
   of answer RRs (along with their packet section assignments) we got
   back in the cache, and use this information to generate reply packets
   from the DNS stub.

In both cases: if we determine a lookup is to be answered from LLMNR or
mDNS we'll always revert to non-DNSSEC, non-proxy operation as before.
Answers will lack the DO bit then, since the data cannot be validated
via DNSSEC by the clients.

To make this logic more debuggable, this also adds query flags for
turning off RR sources. i.e. cache/network/zone/trust anchor/local
synthesis may now be disabled individually for each lookup.

The cache is substantially updated to make all this work: in addition to
caching simple RRs for lookup RR keys, we'll now cache the whole packets
and the whole combination of RRs, so that we can answer DO and DO+CD
replies sensibly according to the rules described above. This sounds
wasteful, but given that the
DnsResourceRecord/DnsResourceKey/DnsAnswer/DnsPacket
objects are all ref-counted and we try to merge references the actual
additional memory used should be limited (but this might be something to
optimize further later on).

To implement classic RR key lookups and new-style packet proxy lookups
(i.e. the ones necessary for DO+CD packet proxying, as described above)
DnsTransaction and DnsQuery objects now always maintain either a
DnsResourceKey/DnsQuestion as lookup key or a DnsPacket for "bypass"
mode.

Fixes: systemd#4621 systemd#17218
xsuchy added a commit to xsuchy/dnf that referenced this issue Feb 10, 2021
because it use systemd-resolved by default, and it cannot do DNSSEC validation
systemd/systemd#4621

Commenting out instead of deleting, to remind us that sometimes in future we can return it back.
Hopefully.
xsuchy added a commit to xsuchy/dnf that referenced this issue Feb 10, 2021
because it use systemd-resolved by default, and it cannot do DNSSEC validation
systemd/systemd#4621

Commenting out instead of deleting, to remind us that sometimes in future we can return it back.
Hopefully.
@pemensik
Copy link
Collaborator

Is it supposed to be fixed? I tried to compile commit 372a500, still no validation is possible via 127.0.0.53.

Global
           Protocols: +LLMNR +mDNS DNSOverTLS=opportunistic DNSSEC=yes/supported                                                         
    resolv.conf mode: foreign                                                                                                            
  Current DNS Server: 127.0.0.1                                                                                                          
         DNS Servers: 127.0.0.1                                                                                                          
Fallback DNS Servers: 1.1.1.1 8.8.8.8 1.0.0.1 8.8.4.4 2606:4700:4700::1111 2001:4860:4860::8888 2606:4700:4700::1001 2001:4860:4860::8844

Link 2 (enp0s31f6)
    Current Scopes: DNS LLMNR/IPv4 LLMNR/IPv6                                               
         Protocols: +DefaultRoute +LLMNR -mDNS DNSOverTLS=opportunistic DNSSEC=yes/supported
Current DNS Server: 192.168.88.9                                                            
       DNS Servers: 192.168.88.9 10.129.26.35 46.149.125.37                                 
        DNS Domain: lan ~.                                                                  
$ build/systemd-resolved --version
systemd 247 (247-1351-g372a500)
+PAM +AUDIT +SELINUX -APPARMOR +IMA +SMACK +SECCOMP +GCRYPT +GNUTLS +OPENSSL +ACL +BLKID +CURL +ELFUTILS +FIDO2 +IDN2 -IDN +IPTC +KMOD +LIBCRYPTSETUP +LIBFDISK +PCRE2 +PWQUALITY +P11KIT +QRENCODE +BZIP2 +LZ4 +XZ +ZLIB +ZSTD +XKBCOMMON +UTMP +SYSVINIT default-hierarchy=unified

$ delv @127.0.0.53
;; validating ./NS: got insecure response; parent indicates it should be secure
;; insecurity proof failed resolving './NS/IN': 127.0.0.53#53
;; resolution failed: insecurity proof failed

$ delv +cd @127.0.0.53
; fully validated
.			508546	IN	NS	m.root-servers.net.
.			508546	IN	NS	a.root-servers.net.
.			508546	IN	NS	b.root-servers.net.
.			508546	IN	NS	c.root-servers.net.
.			508546	IN	NS	d.root-servers.net.
.			508546	IN	NS	e.root-servers.net.
.			508546	IN	NS	f.root-servers.net.
.			508546	IN	NS	g.root-servers.net.
.			508546	IN	NS	h.root-servers.net.
.			508546	IN	NS	i.root-servers.net.
.			508546	IN	NS	j.root-servers.net.
.			508546	IN	NS	k.root-servers.net.
.			508546	IN	NS	l.root-servers.net.
.			508546	IN	RRSIG	NS 8 0 518400 20210224050000 20210211040000 42351 . MSguVdsOaNvuyqPDwrU+O5MMhhCk0pxh0snhRLnE/bE8aExT4mOxzXbo UjSLOo3Fv27fE+PyBM/1eG9FDDT/Bg5E57MHo68JzBqiGHga3NDInVbY dX1xUt8qUgb55XSDV/66QjaweO1zeCXW95XtOj5j0c9CQcMPVldjCbjU HAaWfqp0a6+srugKLF2NgLxpQzi5Be/cA6SklRy2WQifW0JAyrFkpZ+2 TmA85INFqNIPO2TyQAAbyEqXtPSrB0Muot2xNQ8XEMuN1FB8nL6P+o4I q2AVgrArCH/YtZY0igD6ai75bIs/PgntC/PmVhd36W46beWD0WGhQ4Pi AndeOg==


$ delv @192.168.88.9
; fully validated
.			194315	IN	NS	d.root-servers.net.
.			194315	IN	NS	h.root-servers.net.
.			194315	IN	NS	a.root-servers.net.
.			194315	IN	NS	b.root-servers.net.
.			194315	IN	NS	m.root-servers.net.
.			194315	IN	NS	g.root-servers.net.
.			194315	IN	NS	l.root-servers.net.
.			194315	IN	NS	k.root-servers.net.
.			194315	IN	NS	i.root-servers.net.
.			194315	IN	NS	j.root-servers.net.
.			194315	IN	NS	c.root-servers.net.
.			194315	IN	NS	e.root-servers.net.
.			194315	IN	NS	f.root-servers.net.
.			194315	IN	RRSIG	NS 8 0 518400 20210222230000 20210209220000 42351 . QCzDH8eHlHVbx4SxIIwk8xnk6ky/q+zRh8KAUfI98lqHcIP4NLxzCe6f mC2sNX1VcthEy6Lwnobm8OyJCRpNEHedYrS01aMhAVzUfM+/PJ9MWn0w SkmXxyZMJZXF/kl4GDNX0x/GW3+DkeTeZI9+B540Yvj47qJv2bD9nIQG NtE7bDze7bgMJkIuBlEzPfwp7YW5ud8qdC6HdUoEMqygwZcWAiQu8gpb q21z8W5hcdci1OouDFytNWrXAvfSsuR635+GzSj+RZjYo+447uP7lKsK N5aeVQ/BPh5jM32xVO+zwyp7v9Nky1vSP/BchMQ/3cqg3Ee7zobl8OQd CSd/SA==

It does not seem to be fixed to me. Can you explain, why was it closed? Is ability to validate just +cd queries considered sufficient?

@pemensik
Copy link
Collaborator

It does not even fulfill original issue message.

$ dig @127.0.0.53 nonexistant.nlnetlabs.nl +dnssec

; <<>> DiG 9.16.11-RedHat-9.16.11-2.fc32 <<>> @127.0.0.53 nonexistant.nlnetlabs.nl +dnssec
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 35403
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 0, AUTHORITY: 3, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 65494
;; QUESTION SECTION:
;nonexistant.nlnetlabs.nl.	IN	A

;; AUTHORITY SECTION:
nlnetlabs.nlnetlabs.nl.	162	IN	NSEC	notls.nlnetlabs.nl. DNAME RRSIG NSEC
!.nlnetlabs.nl.		162	IN	NSEC	6only.nlnetlabs.nl. TXT RRSIG NSEC
nlnetlabs.nl.		162	IN	SOA	ns.nlnetlabs.nl. hostmaster.nlnetlabs.nl. 2021020900 28800 7200 604800 240

;; Query time: 2 msec
;; SERVER: 127.0.0.53#53(127.0.0.53)
;; WHEN: Čt úno 11 12:01:52 CET 2021
;; MSG SIZE  rcvd: 195

NSEC record have appeared, but RRSIG records are still missing. My upstream server provides them however.

$ dig @192.168.88.9 nonexistant.nlnetlabs.nl +dnssec

; <<>> DiG 9.16.11-RedHat-9.16.11-2.fc32 <<>> @192.168.88.9 nonexistant.nlnetlabs.nl +dnssec
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 17468
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 0, AUTHORITY: 6, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 4096
; COOKIE: d8944339b2e2e4e2d295273260250f2de364867f0def58a6 (good)
;; QUESTION SECTION:
;nonexistant.nlnetlabs.nl.	IN	A

;; AUTHORITY SECTION:
!.nlnetlabs.nl.		240	IN	RRSIG	NSEC 8 3 240 20210309015008 20210209015008 42393 nlnetlabs.nl. edxcSK4MiBcfkiHy0gRnw6GDlz+PJrCLarWeB7tDj6+b1PpfLqXA6Dyn YfDWsXmCzZRO9F3yKdNov62eUMzzlJB1mNQvbIHuzTyv7Pryrn7c3UBh E8GILtVABSYTYXq8quwbthAURvu06WQsBXjA5/9xyT2bKaB4rnIrO9Y0 Ni8=
!.nlnetlabs.nl.		240	IN	NSEC	6only.nlnetlabs.nl. TXT RRSIG NSEC
nlnetlabs.nl.		240	IN	SOA	ns.nlnetlabs.nl. hostmaster.nlnetlabs.nl. 2021020900 28800 7200 604800 240
nlnetlabs.nl.		240	IN	RRSIG	SOA 8 2 240 20210309015008 20210209015008 42393 nlnetlabs.nl. viQ6Sl+9Upd6z8Qk3CXaBIMOfNi5EEzUgnh0v1UGU9Bsvwh2xtqXV4nN YaHcAffqI79mCFyVaIz4Vg5h7gQ3hKvG2hyVgqQabMq7Sa+sG9Qk5PI5 htekwbusQuGiY6mAeo0V68673yHhYYrNf4rR3G7ODLqPsepd0LF0Vwec nM8=
nlnetlabs.nlnetlabs.nl.	240	IN	RRSIG	NSEC 8 3 240 20210309015008 20210209015008 42393 nlnetlabs.nl. ADg88BmzPJo/1uoETtH3OSAaQqdfX1OB9RxxEvzGk6zq7ZDfsygwpTHp 1EP8kS90zvdHa7y8pzPWmbjkwLqyd0Z8iQVVzBqtNZAv/v2GgUiLHAt/ eAjB6dP6GvXLZhyBt6qv5zwpZ5FZ7RxsT7WHeZvCpQGkKXgBH1hEqyTg zpY=
nlnetlabs.nlnetlabs.nl.	240	IN	NSEC	notls.nlnetlabs.nl. DNAME RRSIG NSEC

;; Query time: 159 msec
;; SERVER: 192.168.88.9#53(192.168.88.9)
;; WHEN: Čt úno 11 12:04:13 CET 2021
;; MSG SIZE  rcvd: 739

@pemensik
Copy link
Collaborator

Is this issue tracked now under different id, @keszybz? Is the issue tested first somehow, before closed?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
dnssec resolve RFE 🎁 Request for Enhancement, i.e. a feature request
Development

Successfully merging a pull request may close this issue.