Skip to content

Instantly share code, notes, and snippets.

@dalf
Created September 15, 2021 10:15
Show Gist options
  • Save dalf/ed255cba5d9d19ff2eb17d6fe9fe2736 to your computer and use it in GitHub Desktop.
Save dalf/ed255cba5d9d19ff2eb17d6fe9fe2736 to your computer and use it in GitHub Desktop.
DNSSec
# apt install python3-ldns (no pip package)
import typing
import os
import socket
from enum import IntEnum
try:
import ldns
LDNS_ERROR_TO_STR = {
ldns.LDNS_RCODE_NOERROR: None,
# The 'FormErr' DNS RCODE (1), as defined in RFC1035.
ldns.LDNS_RCODE_FORMERR: 'The name server was unable to interpret the query.',
# The 'ServFail' DNS RCODE (2), as defined in RFC1035.
ldns.LDNS_RCODE_SERVFAIL: 'The name server was unable to process this query due to a problem ' \
+ 'with the name server.', # noqa
# The 'NXDomain' DNS RCODE (3), as defined in RFC1035.
# Domain not found
ldns.LDNS_RCODE_NXDOMAIN: None,
# The 'NotImp' DNS RCODE (4), as defined in RFC1035.
ldns.LDNS_RCODE_NOTIMPL: 'The name server does not support the requested kind of query',
# The 'Refused' DNS RCODE (5), as defined in RFC1035.
ldns.LDNS_RCODE_REFUSED: 'The server refused to answer',
# The 'YXDomain' DNS RCODE (6), as defined in RFC2136.
ldns.LDNS_RCODE_YXDOMAIN: 'Timeout after DNAME substitution',
# The 'YXRRSet' DNS RCODE (7), as defined in RFC2136.
ldns.LDNS_RCODE_YXRRSET: 'Some RRset that ought not to exist, does exist.',
# The 'NXRRSet' DNS RCODE (8), as defined in RFC2136.
ldns.LDNS_RCODE_NXRRSET: 'Some RRset that ought to exist, does not exist.',
# The 'NotAuth' DNS RCODE (9), as defined in RFC2136.
ldns.LDNS_RCODE_NOTAUTH: 'The server is not authoritative for the zone named in the Zone Section.',
# The 'NotZone' DNS RCODE (10), as defined in RFC2136.
ldns.LDNS_RCODE_NOTZONE: 'A name used in the Prerequisite or Update Section is not within the zone ' \
+ 'denoted by the Zone Section.', # noqa
}
STR_TO_LDNS_RR_TYPE = {
'PTR': ldns.LDNS_RR_TYPE_PTR,
'A': ldns.LDNS_RR_TYPE_A,
'AAAA': ldns.LDNS_RR_TYPE_AAAA,
}
except ImportError:
ldns = None
class DnsSecResult(IntEnum):
UNKNOW = 0
SECURE = 1
INSECURE = 2
BOGUS = 3
def dns_query_field_ldns(host: str, field: str):
dns_answers = []
dns_error = None
dnssec_result = DnsSecResult.UNKNOW
resolver = ldns.ldns_resolver.new_frm_file("/etc/resolv.conf")
resolver.set_dnssec(True)
pkt = resolver.query(host, STR_TO_LDNS_RR_TYPE[field], ldns.LDNS_RR_CLASS_IN)
if pkt and pkt.answer():
if pkt.get_rcode() is ldns.LDNS_RCODE_SERVFAIL:
# SERVFAIL indicated bogus name
dnssec_result = DnsSecResult.BOGUS
elif pkt.get_rcode() is ldns.LDNS_RCODE_NOERROR:
# Check AD (Authenticated) bit
if pkt.ad():
dnssec_result = DnsSecResult.SECURE
else:
dnssec_result = DnsSecResult.INSECURE
else:
dns_error = LDNS_ERROR_TO_STR.get(pkt.get_rcode(), "Error")
for rr in pkt.answer().rrs():
if rr.get_type_str() == field:
value = " ".join(str(rdf) for rdf in rr.rdfs())
dns_answers.append(value)
return dns_answers, dns_error, dnssec_result
print(dns_query_field_ldns('anon.sx', 'A'))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment