kyorohiro (kiyohiro kawamura)
Posted on December 26, 2021
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
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 |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
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
}
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 |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
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 |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
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
}
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==
}
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
REF
Posted on December 26, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.