Both explanations are correct, they are just summaries of what happens, so obviously the devil is in the details. Including what shortcuts are used for efficiency, the state of the cache, if QNAME minimization is into play, etc.
But you do not need to think about theories, you can observe in real life.
Use the delv
application. It is described as such:
delv is a tool for sending DNS queries and validating the results, using the same internal resolver and validator logic as named.
So using it show exactly what a (bind) recursive nameserver does, both about records fetching and then DNSSEC validation.
Let us try with: delv +rtrace +vtrace www.icann.org
After some time you get the final results at the end of the output:
; fully validated
www.icann.org. 0 IN CNAME www.vip.icann.org.
www.icann.org. 0 IN RRSIG CNAME 7 3 3600 20191117090520 20191027015903 8150 icann.org. mmVZ3tzEr1rRDXIVF4TiqcnAwyNzA6kV+FXq1/8CSeZfVUa1260NfIxQ TzaV05NHSvW7CqeBXskzmPjCkSAGpF2breelu+k1Qd9CfJ7/+gp38mFO zTddZdZDL+ddU5rlaeaF17OokcPUnBtR23buBmWZ/mK83heXSKrWHfKn lNQ=
www.vip.icann.org. 30 IN A 192.0.32.7
www.vip.icann.org. 30 IN RRSIG A 7 4 30 20191107231353 20191031231353 52760 vip.icann.org. jtvLS1ylxThi0xlObrrDA4nSM5GbpKeBvhcKlRn3em103AIxGAMu7o24 5uzhGQVZn4AsEH62/2JfWYQVavOnsb4rI8+rl5iw/XmUkoy7neBNybB6 kjrfcaUbCNhjgoipGotlUolqlNjKKzkMHbGLdUCMOzdlacfuK1gz825c PuA=
www.vip.icann.org. 30 IN RRSIG A 7 4 30 20191109071334 20191102071334 14702 vip.icann.org. LxEa+CV0bIB9I2s8v9MaK9JXoOEghUiYSotxACrxq2TxclX/6HPWBX+l SF5Y6iQ5ikMTjKd3XjmRO0Bawq+b7NWX2EToGGhGv51Vv69xi8++03zg JoSimnGmLPoOwK/RS8+MOouS2O629ycAa9JGtpy+Erx/tahCc5oRpXfg 6h4=
So first you see that, for this record, DNSSEC was fully validated, and then you see the records themselves (this name is a CNAME).
Now if you get back to previous lines of the output you see how this conclusion was reached.
First, the name resolution itself, and grabing the relevant DS
and DNSKEY
byt climbing back to the root:
;; fetch: www.icann.org/A
;; validating www.icann.org/CNAME: starting
;; validating www.icann.org/CNAME: attempting positive response validation
;; fetch: icann.org/DNSKEY
;; validating icann.org/DNSKEY: starting
;; validating icann.org/DNSKEY: attempting positive response validation
;; fetch: icann.org/DS
;; validating icann.org/DS: starting
;; validating icann.org/DS: attempting positive response validation
;; fetch: org/DNSKEY
;; validating org/DNSKEY: starting
;; validating org/DNSKEY: attempting positive response validation
;; fetch: org/DS
;; validating org/DS: starting
;; validating org/DS: attempting positive response validation
;; fetch: ./DNSKEY
So in summary:
- first getting the record itself, showing it exists in the
icann.org
zone
- so fetching
DNSKEY
records for icann.org
zone
- since they exist, we now need the
DS
records in parent zone, org
- since they exist, we now need the
DNSKEY
records in org
- since they exist, we now need the
DS
records in parent zone, .
- since they exist, we now need the
DNSKEY
records of this .
zone
- and we stop here because we discover that the DNSEY records we got are in fact our trusted key (from
delv
documentation: "-a anchor-file
Specifies a file from which to read DNSSEC trust anchors. The default is /etc/bind.keys, which is included with BIND 9 and contains one or more trust anchors for the root zone (".").
")
You can see that this first step, collecting DS
and DNSKEY
records, was bottom to top.
Now there is the second part of the output, validating th whole chain, and it goes like that:
;; validating ./DNSKEY: starting
;; validating ./DNSKEY: attempting positive response validation
;; validating ./DNSKEY: verify rdataset (keyid=20326): success
;; validating ./DNSKEY: signed by trusted key; marking as secure
;; validating org/DS: in fetch_callback_validator
;; validating org/DS: keyset with trust secure
;; validating org/DS: resuming validate
;; validating org/DS: verify rdataset (keyid=22545): success
;; validating org/DS: marking as secure, noqname proof not needed
;; validating org/DNSKEY: in dsfetched
;; validating org/DNSKEY: dsset with trust secure
;; validating org/DNSKEY: verify rdataset (keyid=9795): success
;; validating org/DNSKEY: marking as secure (DS)
;; validating icann.org/DS: in fetch_callback_validator
;; validating icann.org/DS: keyset with trust secure
;; validating icann.org/DS: resuming validate
;; validating icann.org/DS: verify rdataset (keyid=11324): success
;; validating icann.org/DS: marking as secure, noqname proof not needed
;; validating icann.org/DNSKEY: in dsfetched
;; validating icann.org/DNSKEY: dsset with trust secure
;; validating icann.org/DNSKEY: no DNSKEY matching DS
;; validating icann.org/DNSKEY: verify rdataset (keyid=18060): success
;; validating icann.org/DNSKEY: marking as secure (DS)
;; validating www.icann.org/CNAME: in fetch_callback_validator
;; validating www.icann.org/CNAME: keyset with trust secure
;; validating www.icann.org/CNAME: resuming validate
;; validating www.icann.org/CNAME: verify rdataset (keyid=8150): success
;; validating www.icann.org/CNAME: marking as secure, noqname proof not needed
;; fetch: www.vip.icann.org/A
;; validating www.vip.icann.org/A: starting
;; validating www.vip.icann.org/A: attempting positive response validation
;; fetch: vip.icann.org/DNSKEY
;; validating vip.icann.org/DNSKEY: starting
;; validating vip.icann.org/DNSKEY: attempting positive response validation
;; fetch: vip.icann.org/DS
;; validating vip.icann.org/DS: starting
;; validating vip.icann.org/DS: attempting positive response validation
;; validating vip.icann.org/DS: keyset with trust secure
;; validating vip.icann.org/DS: verify rdataset (keyid=8150): success
;; validating vip.icann.org/DS: marking as secure, noqname proof not needed
;; validating vip.icann.org/DNSKEY: in dsfetched
;; validating vip.icann.org/DNSKEY: dsset with trust secure
;; validating vip.icann.org/DNSKEY: verify rdataset (keyid=45993): success
;; validating vip.icann.org/DNSKEY: marking as secure (DS)
;; validating www.vip.icann.org/A: in fetch_callback_validator
;; validating www.vip.icann.org/A: keyset with trust secure
;; validating www.vip.icann.org/A: resuming validate
;; validating www.vip.icann.org/A: verify rdataset (keyid=52760): success
;; validating www.vip.icann.org/A: marking as secure, noqname proof not needed
As you can see now the process is top to bottom:
- we validate the root key based on local data (trust anchor)
- from that, we validate the DS record for
org
in root zone, as signed by a trusted DNSKEY
- then the correspondig key is considered trusted and is seen as used in a
DS
record for icann.org
- so we do the same step but one zone lower
- and finally we validate the
CNAME
record for www.icann.org
because this is the name we asked for
- but since this is a
CNAME
and user (implicitely) asked for an A
record, the resolution process continue
- and the target of the
CNAME
record is in its own separate delegated record vip.icann.org
so there is again a step of DS
and DNSKEY
records fetch and validation.
- and all finishes well, with
A
record for www.vip.icann.org
being fully validated.