用python读取DNS数据包

2024-09-30 14:22:08 发布

您现在位置:Python中文网/ 问答频道 /正文

This question had been asked before但这个问题从未得到充分解决,而且是从2013年开始的。我使用python套接字来观察DNS数据包,它们看起来是这样的:

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

在研究DNS数据包的基本原理后,我发现它们的结构如下:

QR | OpCode | AA | TC | RD | RA | Z | AD | CD | 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

这只返回一个包含地址名称的字符串,而不返回上面指定的其他信息。其他数据(如QR和操作码)在哪里?我解码错误了吗

说清楚一点,我不想使用外部库,我的目标是了解DNS数据包的结构以及如何解码它们;我知道像dnslibscapy这样的库


Tags: dnsthis解码数据包结构qrquestionbeen
1条回答
网友
1楼 · 发布于 2024-09-30 14:22:08

我不是插座专家。从引用-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)

输出:

DNS包字典 {'ID':257,'QR':False,'Opcode':0,'AA':False,'TC':False,'RD':False,'RA':False,'Z':False,'AD':False,'CD':False,'RCode':False,'QDCOUNT':0,'NSCOUNT':0,'ARCOUNT':3,'QTYPE':1,'QCLASS':0,'QNAME':'www.googletagmanager.com'}

Pyhon位操作

  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-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 1111111-255(128+64+32+16+8+4+2+1)

在python中,int('00000111',2)格式是使用模2(位)转换字符串数组['0'/'1']。这将返回值7乘以10

参考DNS标头: https://www2.cs.duke.edu/courses/fall16/compsci356/DNS/DNS-primer.pdfhttp://www.networksorcery.com/enp/protocol/dns.htm

enter image description hereenter image description here

相关问题 更多 >