DNS/実装/python/dnslib/client.py

   1 # -*- coding: utf-8 -*-
   2 
   3 """
   4     DNS Client - DiG-like CLI utility. 
   5     
   6     Mostly useful for testing. Can optionally compare results from two
   7     nameservers (--diff) or compare results against DiG (--dig).
   8 
   9     Usage: python -m dnslib.client [options|--help]
  10     
  11     See --help for usage.
  12 """
  13 
  14 from __future__ import print_function
  15 
  16 try:
  17     from subprocess import getoutput
  18 except ImportError:
  19     from commands import getoutput
  20 
  21 import binascii,code,pprint
  22 
  23 from dnslib.dns import DNSRecord,DNSHeader,DNSQuestion,QTYPE
  24 from dnslib.digparser import DigParser
  25 
  26 if __name__ == '__main__':
  27 
  28     import argparse,sys,time
  29 
  30     p = argparse.ArgumentParser(description="DNS Client")
  31     p.add_argument("--server","-s",default="8.8.8.8",
  32                     metavar="<address:port>",
  33                     help="Server address:port (default:8.8.8.8:53) (port is optional)")
  34     p.add_argument("--query",action='store_true',default=False,
  35                     help="Show query (default: False)")
  36     p.add_argument("--hex",action='store_true',default=False,
  37                     help="Dump packet in hex (default: False)")
  38     p.add_argument("--tcp",action='store_true',default=False,
  39                     help="Use TCP (default: UDP)")
  40     p.add_argument("--noretry",action='store_true',default=False,
  41                     help="Don't retry query using TCP if truncated (default: false)")
  42     p.add_argument("--diff",default="",
  43                     help="Compare response from alternate nameserver (format: address:port / default: false)")
  44     p.add_argument("--dig",action='store_true',default=False,
  45                     help="Compare result with DiG - if ---diff also specified use alternative nameserver for DiG request (default: false)")
  46     p.add_argument("--short",action='store_true',default=False,
  47                     help="Short output - rdata only (default: false)")
  48     p.add_argument("--debug",action='store_true',default=False,
  49                     help="Drop into CLI after request (default: false)")
  50     p.add_argument("domain",metavar="<domain>",
  51                     help="Query domain")
  52     p.add_argument("qtype",metavar="<type>",default="A",nargs="?",
  53                     help="Query type (default: A)")
  54     args = p.parse_args()
  55 
  56     # Construct request
  57     q = DNSRecord(q=DNSQuestion(args.domain,getattr(QTYPE,args.qtype)))
  58 
  59     address,_,port = args.server.partition(':')
  60     port = int(port or 53)
  61 
  62     if args.query:
  63         print(";; Sending%s:" % (" (TCP)" if args.tcp else ""))
  64         if args.hex:
  65             print(";; QUERY:",binascii.hexlify(q.pack()).decode())
  66         print(q)
  67         print()
  68 
  69     a_pkt = q.send(address,port,tcp=args.tcp)
  70     a = DNSRecord.parse(a_pkt)
  71 
  72     if a.header.tc and args.noretry == False:
  73         # Truncated - retry in TCP mode
  74         a_pkt = q.send(address,port,tcp=True)
  75         a = DNSRecord.parse(a_pkt)
  76 
  77     if args.dig or args.diff:
  78         if args.diff:
  79             address,_,port = args.diff.partition(':')
  80             port = int(port or 53)
  81 
  82         if args.dig:
  83             dig = getoutput("dig +qr -p %d %s %s @%s" % (
  84                                 port, args.domain, args.qtype, address))
  85             dig_reply = list(iter(DigParser(dig)))
  86             # DiG might have retried in TCP mode so get last q/a
  87             q_diff = dig_reply[-2]
  88             a_diff = dig_reply[-1]
  89         else:
  90             q_diff = DNSRecord(header=DNSHeader(id=q.header.id),
  91                                q=DNSQuestion(args.domain,
  92                                              getattr(QTYPE,args.qtype)))
  93             q_diff = q
  94             diff = q_diff.send(address,port,tcp=args.tcp)
  95             a_diff = DNSRecord.parse(diff)
  96             if a_diff.header.tc and args.noretry == False:
  97                 diff = q_diff.send(address,port,tcp=True)
  98                 a_diff = DNSRecord.parse(diff)
  99 
 100     if args.short:
 101         print(a.short())
 102     else:
 103         print(";; Got answer:")
 104         if args.hex:
 105             print(";; RESPONSE:",binascii.hexlify(a_pkt).decode())
 106             if args.diff and not args.dig:
 107                 print(";; DIFF    :",binascii.hexlify(diff).decode())
 108         print(a)
 109         print()
 110 
 111         if args.dig or args.diff:
 112             if q != q_diff:
 113                 print(";;; ERROR: Diff Question differs")
 114                 for (d1,d2) in q.diff(q_diff):
 115                     if d1:
 116                         print(";; - %s" % d1)
 117                     if d2:
 118                         print(";; + %s" % d2)
 119             if a != a_diff:
 120                 print(";;; ERROR: Diff Response differs")
 121                 for (d1,d2) in a.diff(a_diff):
 122                     if d1:
 123                         print(";; - %s" % d1)
 124                     if d2:
 125                         print(";; + %s" % d2)
 126 
 127     if args.debug:
 128         code.interact(local=locals())

MoinQ: DNS/実装/python/dnslib/client.py (last edited 2021-03-04 15:05:38 by ToshinoriMaeno)