TXT フィールド データも解析して、以下のコードを拡張したいと考えています。TXT フィールドのチェックを追加して、データの解析を開始するだけです。ただし、rdata フィールドはリトル エンディアン形式です。正規表現を使用して、Base64 でエンコードされた文字列に付属するガベージを取り除くつもりでしたが、これを行うにはもっと良い方法があると思いました。
#!/usr/bin/env python
import dpkt, socket, sys
if len(sys.argv) < 2 or len(sys.argv) > 2:
print "Usage:\n", sys.argv[0], "filename.pcap"
sys.exit()
f = open(sys.argv[1])
pcap = dpkt.pcap.Reader(f)
for ts, buf in pcap:
# make sure we are dealing with IP traffic
# ref: http://www.iana.org/assignments/ethernet-numbers
try: eth = dpkt.ethernet.Ethernet(buf)
except: continue
if eth.type != 2048: continue
# make sure we are dealing with UDP
# ref: http://www.iana.org/assignments/protocol-numbers/
try: ip = eth.data
except: continue
if ip.p != 17: continue
# filter on UDP assigned ports for DNS
# ref: http://www.iana.org/assignments/port-numbers
try: udp = ip.data
except: continue
if udp.sport != 53 and udp.dport != 53: continue
# make the dns object out of the udp data and check for it being a RR (answer)
# and for opcode QUERY (I know, counter-intuitive)
try: dns = dpkt.dns.DNS(udp.data)
except: continue
if dns.qr != dpkt.dns.DNS_R: continue
if dns.opcode != dpkt.dns.DNS_QUERY: continue
if dns.rcode != dpkt.dns.DNS_RCODE_NOERR: continue
if len(dns.an) < 1: continue
# now we're going to process and spit out responses based on record type
# ref: http://en.wikipedia.org/wiki/List_of_DNS_record_types
for answer in dns.an:
if answer.type == 5:
print "CNAME request", answer.name, "\tresponse", answer.cname
elif answer.type == 1:
print "A request", answer.name, "\tresponse", socket.inet_ntoa(answer.rdata)
elif answer.type == 12:
print "PTR request", answer.name, "\tresponse", answer.ptrname
追加した
elif answer.type == 16:
print "TXT request", repr(answer.name), "\tresponse", repr(answer.rdata)
出力
Cr\xe0ax\xdac`\xe0`p\xe5`0\xf9\x9b\xe3\xc0\xe0\xc0\xf6\xf5\xd7\x81\x15\xc9\x8c@\xcc\xc4 \xb6\xfd\x98\xa7\x8dA\xd9\xf9\nI\xf7\x06\x01\xc6\xf9\x06\xb7\x19\x18\x18\x199\xb8\x18\x98_81\xc8\xfc\xb2\x05\x00\xef|\x115