%PDF- %PDF-
Direktori : /usr/share/doc/python3-dnspython/examples/ |
Current File : //usr/share/doc/python3-dnspython/examples/doh-json.py |
#!/usr/bin/env python3 import copy import json import requests import dns.flags import dns.message import dns.resolver import dns.rdataclass import dns.rdatatype # This shows how to convert to/from dnspython's message object and the # DNS-over-HTTPS (DoH) JSON form used by Google and Cloudflare, and # described here: # # https://developers.google.com/speed/public-dns/docs/doh/json # # There's no need to do this for DoH as dnspython supports the # standard RFC 8484 protocol which all DoH providers implement. The # conversion to/from JSON is useful, however, so we show a way to do # it. # # "simple" below means "simple python data types", i.e. things made of # combinations of dictionaries, lists, strings, and numbers. def make_rr(simple, rdata): csimple = copy.copy(simple) csimple['data'] = rdata.to_text() return csimple def flatten_rrset(rrs): simple = { 'name': str(rrs.name), 'type': rrs.rdtype, } if len(rrs) > 0: simple['TTL'] = rrs.ttl return [make_rr(simple, rdata) for rdata in rrs] else: return [simple] def to_doh_simple(message): simple = { 'Status': message.rcode() } for f in dns.flags.Flag: if f != dns.flags.Flag.AA and f != dns.flags.Flag.QR: # DoH JSON doesn't need AA and omits it. DoH JSON is only # used in replies so the QR flag is implied. simple[f.name] = (message.flags & f) != 0 for i, s in enumerate(message.sections): k = dns.message.MessageSection.to_text(i).title() simple[k] = [] for rrs in s: simple[k].extend(flatten_rrset(rrs)) # we don't encode the ecs_client_subnet field return simple def from_doh_simple(simple, add_qr=False): message = dns.message.QueryMessage() flags = 0 for f in dns.flags.Flag: if simple.get(f.name, False): flags |= f if add_qr: # QR is implied flags |= dns.flags.QR message.flags = flags message.set_rcode(simple.get('Status', 0)) for i, sn in enumerate(dns.message.MessageSection): rr_list = simple.get(sn.name.title(), []) for rr in rr_list: rdtype = dns.rdatatype.RdataType(rr['type']) rrs = message.find_rrset(i, dns.name.from_text(rr['name']), dns.rdataclass.IN, rdtype, create=True) if 'data' in rr: rrs.add(dns.rdata.from_text(dns.rdataclass.IN, rdtype, rr['data']), rr.get('TTL', 0)) # we don't decode the ecs_client_subnet field return message a = dns.resolver.resolve('www.dnspython.org', 'a') p = to_doh_simple(a.response) print(json.dumps(p, indent=4)) response = requests.get('https://dns.google/resolve?', verify=True, params={'name': 'www.dnspython.org', 'type': 1}) p = json.loads(response.text) m = from_doh_simple(p, True) print(m)