Question

i'm writing a program to receive dns messages and respond an appropriate answer(a simple dns server that only reply A records).
but when i receive messages it's not like the described format in 1035 RFC.
for example this is a dns query generated by nslookup:

'\xe1\x0c\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x06google\x03com\x00\x00\x01\x00\x01'

i know about dns headers and bits as defined in 1035 RFC but why it should be in hex?
should i consider them as hex numbers or their utf-8 equivalents?
should my responses have this format too?

Was it helpful?

Solution

It's coming out as hexadecimal because it is a raw binary request, but you are presumably trying to print it out as a string. That is apparently how non-printable characters are displayed by whatever you are using to print it out; it escapes them as hex sequences.

You don't interpret this as "hex" or UTF-8 at all; you need to interpret the binary format described by the RFC. If you mention what language you're using, I (or someone else) might be able to describe to you how to handle data in a binary format like this.

Untile then, let's take a look at RFC 1035 and see how to interpret your query by hand:

The header contains the following fields:

                                    1  1  1  1  1  1
      0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                      ID                       |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |QR|   Opcode  |AA|TC|RD|RA|   Z    |   RCODE   |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                    QDCOUNT                    |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                    ANCOUNT                    |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                    NSCOUNT                    |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                    ARCOUNT                    |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

Each line there is 16 bits, so that's 12 bytes. Lets fill our first 12 bytes into there:

                                    1  1  1  1  1  1
      0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                   ID = e10c                   |  \xe1 \x0c
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    | 0|  Opcode=0 | 0| 0| 1| 0| Z=0    |  RCODE=0  |  \x01 \x00
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                  QDCOUNT = 1                  |  \x00 \x01
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                  ANCOUNT = 0                  |  \x00 \x00
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                  NSCOUNT = 0                  |  \x00 \x00
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                  ARCOUNT = 0                  |  \x00 \x00
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

So. We have a query with ID = e10c (just an arbitrary number so the client can match queries up with responses), QR = 0 indicates that it's a query, opcode = 0 indicates that it's a standard query, AA and TC are for responses, RD = 1 indicates that recursion is desired (we are making a recursive query to our local nameserver). Z is reserved for future use, RCODE is a response code for responses. QDCOUNT = 1 indicates that we have 1 question, all the rest are numbers of different types of records in a response.

Now we come to the questions. Each has the following format:

                                    1  1  1  1  1  1
      0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                                               |
    /                     QNAME                     /
    /                                               /
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                     QTYPE                     |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                     QCLASS                    |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

QNAME is the name the query is about. The format is one octet indicating the length of a label, followed by the label, terminated by a label with 0 length.

So we have:

                                    1  1  1  1  1  1
      0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |       LEN = 6         |           g           |  \x06 g
    |           o           |           o           |  o    o
    |           g           |           l           |  g    l
    |           e           |       LEN = 3         |  e    \x03
    |           c           |           o           |  c    o
    |           m           |       LEN = 0         |  m    \x00
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                   QTYPE = 1                   |  \x00 \x01
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                  QCLASS = 1                   |  \x00 \x01
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

This indicates that the name we are looking up is google.com (sometimes written as google.com., with the empty label at the end made explicit). QTYPE = 1 is an A (IPv4 address) record. QCLASS = 1 is an IN (internet) query. So this is asking for the IPv4 address of google.com.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top