Using dnspython to validate DNSSEC - How to use dns.message.from_file

464 views
Skip to first unread message

Marx Mustermann

unread,
Sep 15, 2021, 2:58:00 PM9/15/21
to dnspython-users
I want to validate DNSSEC offline and store corresponding certificates locally via drill. drill man netlabs ldns/drill
I then want to validate the stored certificate chain using dnspython.

However, I fail to read the stored certificates via dnspython. I have tried among others with dns.message.from_file, but the read file is only incompletely read in a way I do not understand.

An example file created looks like this:
;; ->>HEADER<<- opcode: QUERY, rcode: NOERROR, id: 19207
;; flags: qr rd ra ad ; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 0 
;; QUESTION SECTION:
;; bsi.de. IN DNSKEY

;; ANSWER SECTION:
bsi.de. 4885 IN DNSKEY 256 3 8 AwEAAbk+uPUlkoZeKZ71XBfBzrnrDkfEIYFjugU2gbue+QGP3bjIBnl3YLJNXUPLW+UDlXE+1VRGy9WBTwLD9ka5cwWNy0It4fNnvpI0Y6bR8xSsW88MLf/tWbtYxt16IIohj7sdunoC0U3JWB7mFaXNG/gXLNqtaWPtRJURsV1+dcVb ;{id = 29544 (zsk), size = 1024b}
bsi.de. 4885 IN DNSKEY 257 3 8 AwEAAcrBN29rSzsjyPqHEcygwTJXCJgZ+ASLK2ahyzNoNAt6RB5sK5a66tlNGRZQrZfBeZYJzwMsBGVeTiliSfvCAl40ldUy5c5QLad+VtT1AQnYK6iWAFE29h6hHzgZk4SKcQUDwkw+cW2berlcyDS/Vb5hIGkLg9ArIUUn9HhwC4KGRumswDYBj3cQ4vW8Z0/hnaHKJuTS2Ms+AaN7aAcpycfnCijhh46aYSwd893Mo5j1v1MHbjMzg1NutUggu5RRh1QYKNsl8sHSou7Gmio1mgeC5yHK1f5pc6dR1GMIxeSVcxtW8pVPpPIQCDK3+0sDWy4B27MzWZRTzd8DcoFDYAM= ;{id = 26119 (ksk), size = 2048b}
bsi.de. 4885 IN RRSIG DNSKEY 8 2 14400 20210923153601 20210913153601 26119 bsi.de. f4jOKKsodoe9tnOj2rJlm/u902ByQt6QZqm7wEwhpP5xOJ7q67Na9hYtUt8XDMtGIjnqtLQts1hGLUv8ulAdAki0a/SL1lvT4sjrhjTPhT1C+ImoCR4pmW7nXrb3uJKocY8jyN4gn4QlmPgeNqt09LN2dK2RnYebR8MTWqZWumFVaMinhSjea5AUQn2nSIx0G28O7AoX0UGTOFornpB2PMFQru5kUV+q89c89JE7CmUzCGDM9yhSWfZDQvVNT1xZD6l8UCiuaYN36jI8TdwjYIsAuy17aAo0KAk5EdSDiJeCVRwS7DuEbYVbzAmdxS5JaaQnvf121yZnerKcp9Ixcg==
bsi.de. 4885 IN RRSIG DNSKEY 8 2 14400 20210923153601 20210913153601 29544 bsi.de. ClbKOkbN3YYCoj+jHXyhBLhdopOIhz6bmsmbxUYx6d2EMD8SRe/znY8Tndfrffb1M0vbHt07tXEj7qMzs4hlKeYJv8Vy/+pzm6XFTYK8js5JI/r1fwMhHSh8k+kZkb4xkhrH9Q6bBvzpCVi3F8pMhy3r5GtCTtICtZR9j7IvrUM=

;; AUTHORITY SECTION:

;; ADDITIONAL SECTION:

;; Query time: 32 msec
;; EDNS: version 0; flags: do ; udp: 1232
;; SERVER: 1.1.1.1
;; WHEN: Wed Sep 15 20:48:09 2021
;; MSG SIZE  rcvd: 919

and read via dns.message.from_file("./example.key") the following is imported:
id 35994
opcode QUERY
rcode NOERROR
flags 
;QUESTION
;ANSWER
;AUTHORITY
;ADDITIONAL

In what way must the stored DNS response be formatted so that it is read in completely using dns.message.from_file? Or is there another way serving my purpose to read saved certificates which i overlooked in the documentation?

Bob Halley

unread,
Sep 16, 2021, 9:48:43 AM9/16/21
to dnspython-users
Your input is in the output format of "dig", which is not the format that dns.message.from_text() takes.   Since any data that is not a DNS RR is in the form of a comment, probably the easiest thing to do is use the zone file parser on this file, even though it isn't a zone.  We simple say to parse it as the root zone, and we turn off the sanity checks at the zone origin as well.  Then we can work with the data easily.  E.g. if you take your example file above, and say it has filename "input", then the following works:

import dns.rdatatype
import dns.zone

z = dns.zone.from_file('input', '.', check_origin=False)
for (name, dnskeys) in z.iterate_rdatasets(rdtype=dns.rdatatype.DNSKEY):
    print(f'found {name} DNSKEY rdataset')
    print(dnskeys)
    dnskey_rrsigs = z.get_rdataset(name, dns.rdatatype.RRSIG, dns.rdatatype.DNSKEY)
    if dnskey_rrsigs:
        print(f'found {name} DNSKEY RRSIG rdataset')
        print(dnskey_rrsigs)


Marx Mustermann

unread,
Sep 23, 2021, 2:07:13 PM9/23/21
to dnspython-users
Thank you!
I experimented with this a bit and it solves my problem importing my records. Currently I don't have an easy solution to validate a DNSSEC certificate chain from root to domain. Is there a way to give dnspython the complete certificate chain (DNSKEY records, DS records, RRSIGs) and do the validation automatically? Or do I have to perform this manually with many iterations and individual checks of the appropriate pairs?


Bob Halley

unread,
Sep 23, 2021, 2:19:32 PM9/23/21
to dnspython-users
Dnspython does not have a DNSSEC validator.  You might consider using DNSViz  in addition as it can do extensive and very useful analysis; you can see how it works by going to dnsviz.net.  Your other options are doing all of the complex validation steps yourself, or installing a local full resolver (e.g. Knot Resolver, Unbound, BIND), doing a DNSSEC-aware query to it for the data you want to validate, and verify that the AD bit is set in the response.  I don't recommend the do-it-yourself approach unless you are trying to learn a lot about DNSSEC, as writing a correct and robust validator is a lot of work.
Reply all
Reply to author
Forward
0 new messages