Programmatically check if domains are DNSSEC protected
Using a DNS resolver (e.g. dnspython
), you can query the domain for its DNSKEY RRset and turn on the DO
(dnssec OK) query flag. If the query succeeds, the answer will have the AD
(authenticated data) flag set and will contain the RRSIG signatures for the zone (if it is signed).
Update: a basic example using dnspython
import dns.name
import dns.query
import dns.dnssec
import dns.message
import dns.resolver
import dns.rdatatype
# get nameservers for target domain
response = dns.resolver.query('example.com.',dns.rdatatype.NS)
# we'll use the first nameserver in this example
nsname = response.rrset[0].to_text() # name
response = dns.resolver.query(nsname,dns.rdatatype.A)
nsaddr = response.rrset[0].to_text() # IPv4
# get DNSKEY for zone
request = dns.message.make_query('example.com.',
dns.rdatatype.DNSKEY,
want_dnssec=True)
# send the query
response = dns.query.udp(request,nsaddr)
if response.rcode() != 0:
# HANDLE QUERY FAILED (SERVER ERROR OR NO DNSKEY RECORD)
# answer should contain two RRSET: DNSKEY and RRSIG(DNSKEY)
answer = response.answer
if len(answer) != 2:
# SOMETHING WENT WRONG
# the DNSKEY should be self signed, validate it
name = dns.name.from_text('example.com.')
try:
dns.dnssec.validate(answer[0],answer[1],{name:answer[0]})
except dns.dnssec.ValidationFailure:
# BE SUSPICIOUS
else:
# WE'RE GOOD, THERE'S A VALID DNSSEC SELF-SIGNED KEY FOR example.com
To see if a particular request is protected, look at the DO flag in the request packet. Whatever language and library you use to interface to DNS should have an accessor for it (it may be called something else, like "dnssec").
The first answer is correct but incomplete if you want to know if a certain zone is protected. The described procedure will tell you if the zone's own data is signed. In order to check that the delegation to the zone is protected, you need to ask the parent zone's name servers for a (correctly signed) DS record for the zone you're interested in.