0

So what I'm trying to do is extract the domain name, e.g. youtube.com, from a dns query using python.

This is the code that I am using to generate my query data. :

import socket

port = 53
ip = '127.0.0.1'

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind((ip, port))

while 1:
    data, addr = sock.recvfrom(512)
    print(data)

The query data returned by the code is a hex string:

                              e2 58 01 00 00 01                   
00 00 00 00 00 01 07 79 6f 75 74 75 62 65 03 63                   
6f 6d 00 00 1c 00 01 00 00 29 02 00 00 00 00 00                   
00 00

And I would like to extract the domain name:

07 79 6f 75 74 75 62 65 03 63                   
6f 6d 00

Maybe something similar to this answer but for the query not the response

I am using python 3.8

Josh
  • 75
  • 1
  • 7
  • You could use the `struct` module to break out the bytes/words that make up the DNS message header and contained parts. There have been many updates to DNS over the years but [RFC 1035](https://tools.ietf.org/html/rfc1035) is likely all you'll need here. Section 4 defines the header and general message structure and section 3 defines the resource records. – tdelaney Dec 03 '20 at 19:03
  • Why don't you use the `dnspython` library? Things are far more complicated than you think, specifically for names that can be compressed, so the point is really not just reading some bytes out of a packet. – Patrick Mevzek Dec 04 '20 at 00:44

1 Answers1

1

You have everything you need inside the dnspython library, and it will save you a lot of headaches as DNS messages are complicated (name compression, pseudo records, etc.)

Without any precautions nor error handling:


In [1]: stream='e2 58 01 00 00 01 00 00 00 00 00 01 07 79 6f 75 74 75 62 65 03 63 6f 6d 00 00 1c 00 01 00 00 29 02 00 00 00 00 00 00 00'

In [7]: data=''.join(chr(int(x, base=16)) for x in stream.split(' '))

In [8]: print data
�Xyoutubecom)

In [9]: import dns

In [10]: import dns.message

In [11]: m = dns.message.from_wire(data)

In [12]: print m
id 57944
opcode QUERY
rcode NOERROR
flags RD
edns 0
payload 512
;QUESTION
youtube.com. IN AAAA
;ANSWER
;AUTHORITY
;ADDITIONAL

In [15]: print m.question[0].name
youtube.com.

In DNS, queries and responses share the same format, hence the dnspython library giving you a Message class to handle those.

Patrick Mevzek
  • 10,995
  • 16
  • 38
  • 54