अजगर में DNS पैकेट पढ़ना

Nov 29 2020

यह प्रश्न पहले भी पूछा गया था, लेकिन सवाल कभी भी पूरी तरह से संबोधित नहीं किया गया था, और 2013 से है। मैं DNS पैकेटों का निरीक्षण करने के लिए अजगर सॉकेट का उपयोग कर रहा हूं, वे इस तरह दिखाई देते हैं:

b'\x01\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x03www\x10googletagmanager\x03com\x00\x00\x01\x00\x01'

DNS पैकेट के मूल सिद्धांतों पर शोध करने पर, मैंने पाया कि वे इस तरह संरचित हैं:

क्यूआर | ओपकोड | एए | टीसी | आरडी | रा | जेड | विज्ञापन | सीडी | RCODE

मैंने पैकेट को 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

यह केवल पते के नाम के साथ एक एकल स्ट्रिंग लौटाता है, और ऊपर निर्दिष्ट के रूप में अन्य जानकारी नहीं। क्यूआर और ओपकोड जैसे बाकी डेटा कहां है? क्या मैं इसे गलत तरीके से डिकोड कर रहा हूं?

स्पष्ट होने के लिए, मैं एक बाहरी पुस्तकालय का उपयोग नहीं करना चाहता हूं और मेरा उद्देश्य यह समझना है कि DNS पैकेट कैसे संरचित हैं और उन्हें कैसे डीकोड करना है; मुझे पुस्तकालयों के बारे में जानकारी है जैसे कि dnslibऔर scapy

जवाब

2 frankr6591 Nov 29 2020 at 21:50

मैं सॉकेट विशेषज्ञ नहीं हूं। संदर्भ से - DNS हेडर बिट्स नहीं बाइट्स से बना होता है ... इसलिए आपको इसे बिट्स के रूप में पार्स करने की आवश्यकता है। बाइट्स और मास्क बिट्स का उपयोग करें। नीचे नमूना देखें। यह अनिश्चित है कि हेडर hdr [12:] की क्या सामग्री है?

यहाँ उपरोक्त नमूने के आधार पर कुछ नमूना कोड दिए गए हैं:

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)

OUTPUT:

DNS पैकेट शब्दकोश {'ID': 257, 'QR': गलत, 'Opcode': 0, 'AA': गलत, 'TC': गलत, 'RD': गलत, 'RA': गलत, 'Z: गलत, 'AD': गलत, 'CD': गलत, 'RCode': गलत, 'QDCOUNT': 0, 'ANCOUNT': 0, 'NSCOUNT': 0, 'ARCOUNT': 3, 'QTVPE': 1, 1 'QCLASS': 0, 'QNAME': 'www.googletagmanager.com'}

पायोन बिट मैनीपुलेशन

को देखें

  1. https://wiki.python.org/moin/BitManipulation
  2. http://www.java2s.com/Tutorials/Python/Data_Types/How_to_create_integer_in_Python_octal_binary_hexadecimal_and_long_integer.htm

एक बाइट ( b'xxxx') 4 बाइट्स का प्रतिनिधित्व करता है। प्रत्येक बाइट 8 बिट से बना होता है

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) + ४ + २ + १)

अजगर में प्रारूप int ('00000111', 2) स्ट्रिंग्स की एक सरणी को बदल देता है ['0' / '1'] modulo 2 (बिट्स) का उपयोग करके। यह 7 modulo 10 का मान देता है।

संदर्भ DNS हेडर: https://www2.cs.duke.edu/courses/fall16/compsci356/DNS/DNS-primer.pdf http://www.networksorcery.com/enp/protocol/dns.htm