%PDF- %PDF-
| Direktori : /lib/python3/dist-packages/dnslib/ |
| Current File : //lib/python3/dist-packages/dnslib/client.py |
# -*- coding: utf-8 -*-
"""
DNS Client - DiG-like CLI utility.
Mostly useful for testing. Can optionally compare results from two
nameservers (--diff) or compare results against DiG (--dig).
Usage: python -m dnslib.client [options|--help]
See --help for usage.
"""
from __future__ import print_function
try:
from subprocess import getoutput,getstatusoutput
except ImportError:
from commands import getoutput,getstatusoutput
import binascii,code,pprint,sys
from dnslib.dns import DNSRecord,DNSHeader,DNSQuestion,DNSError,QTYPE,EDNS0
from dnslib.digparser import DigParser
if __name__ == '__main__':
import argparse,sys,time
p = argparse.ArgumentParser(description="DNS Client")
p.add_argument("--server","-s",default="8.8.8.8",
metavar="<address:port>",
help="Server address:port (default:8.8.8.8:53) (port is optional)")
p.add_argument("--query",action='store_true',default=False,
help="Show query (default: False)")
p.add_argument("--hex",action='store_true',default=False,
help="Dump packet in hex (default: False)")
p.add_argument("--tcp",action='store_true',default=False,
help="Use TCP (default: UDP)")
p.add_argument("--noretry",action='store_true',default=False,
help="Don't retry query using TCP if truncated (default: false)")
p.add_argument("--diff",default="",
help="Compare response from alternate nameserver (format: address:port / default: false)")
p.add_argument("--dig",action='store_true',default=False,
help="Compare result with DiG - if ---diff also specified use alternative nameserver for DiG request (default: false)")
p.add_argument("--short",action='store_true',default=False,
help="Short output - rdata only (default: false)")
p.add_argument("--dnssec",action='store_true',default=False,
help="Set DNSSEC (DO/AD) flags in query (default: false)")
p.add_argument("--debug",action='store_true',default=False,
help="Drop into CLI after request (default: false)")
p.add_argument("domain",metavar="<domain>",
help="Query domain")
p.add_argument("qtype",metavar="<type>",default="A",nargs="?",
help="Query type (default: A)")
args = p.parse_args()
# Construct request
try:
q = DNSRecord(q=DNSQuestion(args.domain,getattr(QTYPE,args.qtype)))
if args.dnssec:
q.add_ar(EDNS0(flags="do",udp_len=4096))
q.header.ad = 1
address,_,port = args.server.partition(':')
port = int(port or 53)
if args.query:
print(";; Sending%s:" % (" (TCP)" if args.tcp else ""))
if args.hex:
print(";; QUERY:",binascii.hexlify(q.pack()).decode())
print(q)
print()
a_pkt = q.send(address,port,tcp=args.tcp)
a = DNSRecord.parse(a_pkt)
if q.header.id != a.header.id:
raise DNSError('Response transaction id does not match query transaction id')
if a.header.tc and args.noretry == False:
# Truncated - retry in TCP mode
a_pkt = q.send(address,port,tcp=True)
a = DNSRecord.parse(a_pkt)
if args.dig or args.diff:
if args.diff:
address,_,port = args.diff.partition(':')
port = int(port or 53)
if args.dig:
if getstatusoutput("dig -v")[0] != 0:
p.error("DiG not found")
if args.dnssec:
dig = getoutput("dig +qr +dnssec -p %d %s %s @%s" % (
port, args.domain, args.qtype, address))
else:
dig = getoutput("dig +qr +noedns +noadflag -p %d %s %s @%s" % (
port, args.domain, args.qtype, address))
dig_reply = list(iter(DigParser(dig)))
# DiG might have retried in TCP mode so get last q/a
q_diff = dig_reply[-2]
a_diff = dig_reply[-1]
else:
q_diff = DNSRecord(header=DNSHeader(id=q.header.id),
q=DNSQuestion(args.domain,
getattr(QTYPE,args.qtype)))
q_diff = q
diff = q_diff.send(address,port,tcp=args.tcp)
a_diff = DNSRecord.parse(diff)
if a_diff.header.tc and args.noretry == False:
diff = q_diff.send(address,port,tcp=True)
a_diff = DNSRecord.parse(diff)
if args.short:
print(a.short())
else:
print(";; Got answer:")
if args.hex:
print(";; RESPONSE:",binascii.hexlify(a_pkt).decode())
if args.diff and not args.dig:
print(";; DIFF :",binascii.hexlify(diff).decode())
print(a)
print()
if args.dig or args.diff:
if q != q_diff:
print(";;; ERROR: Diff Question differs")
for (d1,d2) in q.diff(q_diff):
if d1:
print(";; - %s" % d1)
if d2:
print(";; + %s" % d2)
if a != a_diff:
print(";;; ERROR: Diff Response differs")
for (d1,d2) in a.diff(a_diff):
if d1:
print(";; - %s" % d1)
if d2:
print(";; + %s" % d2)
if args.debug:
code.interact(local=locals())
except DNSError as e:
p.error(e)