Membaca paket DNS dengan python
Pertanyaan ini telah ditanyakan sebelumnya tetapi pertanyaan itu tidak pernah dijawab sepenuhnya, dan dari tahun 2013. Saya menggunakan soket python untuk mengamati paket DNS, mereka tampak seperti ini:
b'\x01\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x03www\x10googletagmanager\x03com\x00\x00\x01\x00\x01'
Setelah meneliti dasar-dasar paket DNS, saya menemukan mereka terstruktur seperti ini:
QR | OpCode | AA | TC | RD | RA | Z | AD | CD | RCODE
Saya kemudian mendekodekan paket ke ASCII:
>> str = b'\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03www\x10googletagmanager\x03com\x00\x00\x01\x00\x01'
>> print(str.decode("ascii"))
wwwgoogletagmanagercom
Ini hanya mengembalikan satu string dengan nama alamat, dan bukan info lain seperti yang ditentukan di atas. Di mana data lainnya, seperti QR dan OpCode? Apakah saya salah mendekodekannya?
Untuk lebih jelasnya, saya tidak ingin menggunakan pustaka eksternal dan tujuan saya adalah untuk memahami bagaimana paket DNS disusun dan bagaimana memecahkan kodenya; Saya mengetahui perpustakaan seperti dnslib
dan scapy
.
Jawaban
Saya bukan ahli soket. Dari referensi - header DNS terdiri dari bit, bukan byte ... jadi Anda perlu menguraikannya sebagai bit. Gunakan byte dan bit mask. Lihat contoh di bawah. Tidak yakin apa isi dari header hdr [12:] itu?
Berikut beberapa contoh kode berdasarkan spesifikasi di atas:
def DNStoDict(hdr):
'''
Parse QNAME by using length (byte) +data sequence -- final length=0 signifies end of QNAME
Refer to https://stackoverflow.com/questions/34841206/why-is-the-content-of-qname-field-not-the-original-domain-in-a-dns-message
1) DNS knows nothing of URLs. DNS is older than the concept of a URL.
2) Because that's how DNS's wire format works. What you see is the
domain name www.mydomain.com, encoded in the DNS binary format.
Length+data is a very common way of storing strings in general.
'''
# Build DNS dictionary of values... include QNAME
l = len(hdr)
argSize = hdr[10]*256+hdr[11]
dnsDict = dict(ID = hdr[0]*256+hdr[1],
QR = bool(hdr[2] & int('10000000', 2)),
Opcode = (hdr[2] & int('01111000', 2))>>3,
AA = bool(hdr[2] & int('00000100', 2)),
TC = bool(hdr[2] & int('00000010', 2)),
RD = bool(hdr[2] & int('00000001', 2)),
RA = bool(hdr[3] & int('10000000', 2)),
Z = bool(hdr[3] & int('01000000', 2)),
AD = bool(hdr[3] & int('00100000', 2)),
CD = bool(hdr[3] & int('00010000', 2)),
RCode = bool(hdr[3] & int('00001111', 2)),
QDCOUNT = hdr[4]*256+hdr[5],
ANCOUNT = hdr[6]*256+hdr[7],
NSCOUNT = hdr[8]*256+hdr[9],
ARCOUNT = argSize,
QTYPE = hdr[l-4]*256+hdr[l-3],
QCLASS = hdr[l-2]*256+hdr[l-2])
# Parse QNAME
n = 12
mx = len(hdr)
qname = ''
while n < mx:
try:
qname += hdr[n:n+argSize].decode() + '.'
n += argSize
argSize = int(hdr[n])
n += 1
if argSize == 0 :
break
except Exception as err:
print("Parse Error", err, n, qname)
break
dnsDict['QNAME'] = qname[:-1]
return dnsDict
# Sample DNS Packet Data
hdr = b'\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03www\x10googletagmanager\x03com\x00\x00\x01\x00\x01'
# Parse out the QNAME
dnsDict = DNStoDict(hdr)
print("\n DNS PACKET dictionary")
print(dnsDict)
KELUARAN:
Kamus PACKET DNS {'ID': 257, 'QR': False, 'Opcode': 0, 'AA': False, 'TC': False, 'RD': False, 'RA': False, 'Z': Salah, 'AD': False, 'CD': False, 'RCode': False, 'QDCOUNT': 0, 'ANCOUNT': 0, 'NSCOUNT': 0, 'ARCOUNT': 3, 'QTYPE': 1, 'QCLASS': 0, 'QNAME': 'www.googletagmanager.com'}
Manipulasi Bit Pyhon
Mengacu pada
- https://wiki.python.org/moin/BitManipulation
- http://www.java2s.com/Tutorials/Python/Data_Types/How_to_create_integer_in_Python_octal_binary_hexadecimal_and_long_integer.htm
Sebuah byte ( b'xxxx'
) mewakili 4 byte. Setiap byte terdiri dari 8 bit
0000 0000 - 0 0000 0001 - 1 0000 0010 - 2 0000 0100 - 4 0000 1000 - 8 0001 0000 - 16 0010 0000 - 32 0100 0000 - 64 1000 0000 - 128 1111 1111 - 255 (128 + 64 + 32 + 16 + 8 + 4 + 2 + 1)
Dalam python, format int ('00000111', 2) mengubah array string ['0' / '1'] menggunakan modulo 2 (bits). Ini mengembalikan nilai 7 modulo 10.
Referensi Header DNS: https://www2.cs.duke.edu/courses/fall16/compsci356/DNS/DNS-primer.pdf http://www.networksorcery.com/enp/protocol/dns.htm

