pythondnsdnssec

Programmatically check if domains are DNSSEC protected


As the title says I want to programmatically check if a DNS response for a domain are protected with DNSSEC.
How could I do this?

It would be great, if there is a pythonic solution for this.

UPDATE: changed request to response, sorry for the confusion


Solution

  • 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