Created
September 15, 2021 10:15
-
-
Save dalf/ed255cba5d9d19ff2eb17d6fe9fe2736 to your computer and use it in GitHub Desktop.
DNSSec
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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