Python'da DNS paketini okuma
Bu soru daha önce sorulmuştu, ancak soru hiçbir zaman tam olarak ele alınmadı ve 2013'ten itibaren. DNS paketlerini gözlemlemek için python soketleri kullanıyorum, öyle görünüyorlar:
b'\x01\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x03www\x10googletagmanager\x03com\x00\x00\x01\x00\x01'
DNS paketlerinin temellerini araştırdıktan sonra, şu şekilde yapılandırıldıklarını buldum:
QR | İşlem Kodu | AA | TC | RD | RA | Z | AD | CD | RCODE
Daha sonra paketi ASCII olarak çözdüm:
>> 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
Bu yalnızca adresin adını içeren tek bir dize döndürür ve yukarıda belirtilen diğer bilgileri döndürmez. QR ve İşlem Kodu gibi verilerin geri kalanı nerede? Yanlış mı çözüyorum?
Açık olmak gerekirse, harici bir kitaplık kullanmak istemiyorum ve amacım DNS paketlerinin nasıl yapılandırıldığını ve bunların nasıl çözüleceğini anlamak; Ben gibi kütüphanelerin farkındayım dnslibve scapy.
Yanıtlar
Soket uzmanı değilim. Referanstan - DNS başlığı bayt değil bitlerden oluşur ... bu nedenle onu bit olarak ayrıştırmanız gerekir. Bayt ve maske bitlerini kullanın. Aşağıdaki örneğe bakın. Hdr [12:] başlığının hangi içeriğinin olduğundan emin değil misiniz?
İşte yukarıdaki spesifikasyona dayalı bazı örnek kodlar:
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)
ÇIKTI:
DNS PAKET sözlüğü {'ID': 257, 'QR': False, 'Opcode': 0, 'AA': False, 'TC': False, 'RD': False, 'RA': False, 'Z': False, 'AD': False, 'CD': False, 'RCode': False, 'QDCOUNT': 0, 'ANCOUNT': 0, 'NSCOUNT': 0, 'ARCOUNT': 3, 'QTYPE': 1, 'QCLASS': 0, 'QNAME': 'www.googletagmanager.com'}
Pyhon Bit Manipülasyonu
Bakın
- 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
Bir bayt ( b'xxxx') 4 baytı temsil eder. Her bayt 8 bitten oluşur
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)
Python'da int ('00000111', 2) biçimi, modulo 2 (bit) kullanarak bir dizi ['0' / '1'] dönüştürür. Bu, 7 modulo 10 değerini döndürür.
Referans DNS Başlığı: https://www2.cs.duke.edu/courses/fall16/compsci356/DNS/DNS-primer.pdf http://www.networksorcery.com/enp/protocol/dns.htm