Create DNS Query In Dart Language

kyorohiro

kyorohiro (kiyohiro kawamura)

Posted on December 26, 2021

Create DNS Query In Dart Language

In this Section, I will explain how to create DNS Query for getting a A Record.

And, in this section, We will try to use Google's Public DNS.
By sending a Get request to

https://dns.google/dns-query?dns=${base64ized DNS Message}

You can retrieve a record from DNS by sending a Get request to

DNS Message Format

The DNS format consists of five sections: Header, Question, Answer, Authority, Additional.

4. MESSAGES

4.1. Format

    +---------------------+
    |        Header       |
    +---------------------+
    |       Question      | the question for the name server
    +---------------------+
    |        Answer       | RRs answering the question
    +---------------------+
    |      Authority      | RRs pointing toward an authority
    +---------------------+
    |      Additional     | RRs holding additional information
    +---------------------+

from https://datatracker.ietf.org/doc/html/rfc1035
Enter fullscreen mode Exit fullscreen mode

Header for Request

Header Section is following format.

4.1.1. Header section format
                                    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                    |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

Enter fullscreen mode Exit fullscreen mode

But if you just want to get A RECORD, you can do the following

  • ID can be anything.
  • RD will be 1.
  • QDCOUNT will be 1.
  • Otherwise, it can be 0.

Let's write this at dart.


var buffer = DNSBuffer(12);

void setInt16AtBE(Uint8List _buffer, int index, int value) {
  _buffer[index + 0] = (value >> 8) & 0xFF;
  _buffer[index + 1] = (value >> 0) & 0xFF;
}

void main() {
  var buffer = Uint8List(12);
  for (var i = 0; i < 12; i++) {
    buffer[i] = 0;
  }
  setInt16AtBE(buffer, 0, 0x1234);
  buffer[2] = 0x01;
  setInt16AtBE(buffer, 5, 0x01);
  print(toHex(buffer)); // 123401000001000000000000
}

Enter fullscreen mode Exit fullscreen mode

Question for Request

                                    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                    |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

Enter fullscreen mode Exit fullscreen mode

The format of the Question's Section is as above, and for QNAME If you want to get A RECORD,

QTYPE should be set to 1
QCLASS should be set to 1

QNAME should be set to the domain name, not a string like github.com.

QNAME

       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    12 |           6           |           g           |
       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    14 |           i           |           t           |
       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    16 |           h           |           u           |
       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    26 |           b           |           3           |
       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    28 |           c           |           o           |
       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    30 |           m           |           0           |
       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

Enter fullscreen mode Exit fullscreen mode

The above is a single-byte number, an ASCII string, a single-byte number, and an ASCII string.

The Null character is added at the end.

Let's write this at dart.


void main() {
  var host = 'github.com';
  var splitHost = host.split('.');
  // Calc Buffer Size
  var length = splitHost.length;
  splitHost.forEach((e) {
    length += e.length;
  });
  length += 1; // NULL CHAR
  length += 4; // CLASS  AND TYPE

  // Set Value
  var buffer = Uint8List(length);
  for (var i = 0; i < 12; i++) {
    buffer[i] = 0;
  }

  var index = 0;
  splitHost.forEach((e) {
    buffer[index++] = e.length;
    for (var i = 0; i < e.length; i++) {
      buffer[index++] = ascii.encode(e.substring(i, i + 1))[0];
    }
  });

  setInt16AtBE(buffer, length - 4, 0x01);
  setInt16AtBE(buffer, length - 2, 0x01);
  print(toHex(buffer)); // 0667697468756203636f6d0000010001
}

Enter fullscreen mode Exit fullscreen mode

Request at Browser

If you combine the Header and Question, you get 1234010000010000000000000667697468756203636f6d0000010001 byte data. When converted to Base64,

import 'dart:typed_data' show Uint8List;
import 'dart:convert' show base64;

Uint8List fromHexString(String hexSrc) {
  var _buffer = Uint8List(hexSrc.length ~/ 2);
  for (var i = 0, j = 0; i < hexSrc.length; i += 2, j++) {
    var v = int.parse(hexSrc.substring(i, i + 2), radix: 16);
    _buffer[j] = v & 0xFF;
  }
  return _buffer;
}

void main() {
  var buffer = fromHexString('1234010000010000000000000667697468756203636f6d0000010001');
  print(base64.encode(buffer)); // EjQBAAABAAAAAAAABmdpdGh1YgNjb20AAAEAAQ==
}

Enter fullscreen mode Exit fullscreen mode

it becomes EjQBAAABAAAAAAAABmdpdGh1YgNjb20AAAEAAQ==

From this, if we remove == and apply it to the Google Public DNS address, we get the following

https://dns.google/dns-query?dns=EjQBAAABAAAAAAAABmdpdGh1YgNjb20AAAEAAQ

You can get following DNS Response

1234818000010001000000000667697468756203636f6d0000010001c00c000100010000003c000434c04859
Enter fullscreen mode Exit fullscreen mode

REF

https://github.com/kyorohiro/dart2.dns

https://datatracker.ietf.org/doc/html/rfc1035

💖 💪 🙅 🚩
kyorohiro
kyorohiro (kiyohiro kawamura)

Posted on December 26, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

DNS Compression In Dart
dart DNS Compression In Dart

December 28, 2021

Create DNS Query In Dart Language
dart Create DNS Query In Dart Language

December 26, 2021