***************************
*** DNS
TUTORIAL ***
***************************
By Frank Dekervel
(kervel@hotmail.com)
Belgium
CONTENTS
1 : about this
document
2 : the domain name system
3 : DNS questions and
answers
* DNS packets explained
* file format for DNS
ABOUT THIS
DOCUMENT
-------------------
Because the DNS is quite difficult to
understand, and there are no really
good tutorials available, i will try to
make my own. I hope it will be easy
to understand. In later versions of this
document, i'll include code for
Borland Delphi or C++.
This tutorial
is *NOT* the only thing you need to learn about the DNS proto.
If you
want to master the DNS, i suggest the following things
* download rfc
1034 for background information, and the model.
* download rfc 1035 (Domain
names : specification and implementation)
*
http://users.neca.com/vmis/
download all the tutorials about the tcp/ip suite
, including winsock,
IP, DNS, PPP,... and many more.
* read this
tutorial
This document may be distributed, but i kindly ask to report me
distributions
or changes.
Since i'm not a native speaker, and since i'm
not an expert, there are errors
in this file. Please report them to me at
kervel@hotmail.com
Oh, yeah, this document is written in windows notepad,
and hase a sucking
layout. Feel free to format this doc and send it back to
me :)
THE DOMAIN NAME SYSTEM
----------------------
To continue
with this tutorial you will need some background information.
A brief history
of domain names can be found in rfc1034 or rfc1035, and read
rfc1035 to know
what DNS, recursion, name servers and resolvers are.
DNS mainly uses UDP
(port 53), but a DNS server also should accept TCP
(also port 53). The
advantage of UDP is speed, but if you need to do a large
number of requests,
you'ld better use TCP.
DNS : QUESTIONS AND
ANSWERS
---------------------------
To demonstrate a DNS request, i ll
start from this packet.
Below, you see a DNS request for space.vadium.sk via
an ethernet device.
Don't mind the ethernet, IP and UDP headers, the DNS
request starts from 2A
The packet is not valid, because it is broadcasted to
192.168.0.255
ORIGINAL DATA:
ےےےےےے èط5ٍ E =ل 7^ہ¨ ہ¨
ےc 5 )™‘Q) sp
acevadiumsk
HEX-DUMP:
OFFSET 00 01 02 03 04 05 06 07-08 09 0A 0B 0C
0D 0E 0F
------ -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
000 FF FF
FF FF FF FF 00 00-E8 D8 35 F2 08 00 45 00 ےےےےےے..èط5ٍ.E.
010 00 3D E1 01 00
00 20 11-37 5E C0 A8 00 01 C0 A8 .=ل.. 7^ہ¨.ہ¨
020 00 FF 04 63 00 35 00
29-99 91 51 29 01 00 00 01 .ےc.5.)™‘Q)..
030 00 00 00 00 00 00 05 73-70 61
63 65 06 76 61 64 ......spacevad
040 69 75 6D 02 73 6B 00 00-01 00 01
iumsk...
ANALYSIS:
ETHERNET PACKET ANALYSIS
Packet
Length :75 Bytes (0x0000004B)
Source Ethernet address
:0.0.232.216.53.242
Destination Ethernet address
:255.255.255.255.255.255
Packet Type :0x0800
IP HEADER
ANALYSIS
IP source address 192.168.0.1
IP dest address
192.168.0.255
Version + header 0x45
TOS (Type of service) 0x00
IP
packet length 61 Bytes (0x003D)
IP fragmentation ID 57601 (0xE101)
IP
flags byte 0x00
Time to live 0x20
protocol Type 0x11
IP checksum
0x375E
UDP HEADER ANALYSIS
UDP source port 1123 (0x0463)
UDP
dest. port 53 (0x0035)
UDP length 41 (0x0029)
UDP checksum 0x9991
*
a few words about the string format used in DNS
Look at offset 0x36,
there you see a string: 05 space 06 vadium 02 sk 00
Like in C, strings are
terminated with a 00 , but each "." (which, in domain
names, separates
domains from subdomains ..) is changed into a byte,
displaying the length of
the next piece. So, to make a right string of
www.altavista.digital.com, u
should do the following :
- www : 3 letters
- altavista : 9
letters
- digital : 7 letters
- com : 3 letters
the string is 0x03 +
"www" + 0x09 + "altavista" + 0x07 + "digital" + 0x03
+ "com" +
0x00
* DNS compression
To reduce size of a DNS packet, a
compression sheme exists. So, if we need
two times the string
'www.altavista.digital.com' in or packet, we only
write it once, and we
change the second and third ... occurence into a
pointer. A (16bit) pointer
looks like this
:
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| 1 1| OFFSET
|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
Thus, if the first
caracter of a string is non-ascii, it is probably a pointer.
If you make a
resolver or a server, make sure your application recognizes
such
pointers.
You can represent a domain name like this
* a DNS string
, terminated with 0x00 (like above)
* a pointer (like here)
* a mixed form
: first a DNS string, without 0x00 termination, but terminated
by a
pointer.
* the DNS packet
A DNS packet consist of this : (the
following things are stolen from rfc1035)
+---------------------+
| Header
|
+---------------------+
| Question | the question for the name
server
+---------------------+
| Answer | RRs answering the
question
+---------------------+
| Authority | RRs pointing toward an
authority
+---------------------+
| Additional | RRs holding additional
information
+---------------------+
* the DNS header
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
|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
where:
ID :
a number to identify the request. The answer will have the same ID
useful for
multiple simultaneous requests : so, you'll know which
answer belongs to
which request.
The next 16 bits are the flags:
// QR 0 BIT
0=request,1=answer
// OPCODE 0 4BIT 0=req,1=inverse,2=status
// AA 0 BIT
0=authority,1=-~
// TC 0 BIT 0=-~,1=truncated
// RD 1 BIT 0=-~,1=recursion
desired
// RA 0 BIT 0=-~,1=recursion available
// ZERO 0 3BIT ALWAYS
ZERO
// RCODE 0 4BIT 0=-~,1=error occured
// for values of RCODE, view
rfc1035
After that, we have the number of requests, the number of
answers, the
number of authenticy records and the number of additional
records.
* the DNS request section (question)
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 a DNS
string (we discussed above), and Qtype is the type of the
Query. For
the type codes see a page below. Qclass is always
0x0001 for internet. Now u
should be able to decode the request packet
in the beginning of this
tutorial.
* RR's (Resource records)
Answer, authority and
additional all use the RR format.
The RR format looks like this :
1 1 1 1
1 1
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4
5
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| |
/ /
/ NAME
/
| |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| TYPE
|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| CLASS
|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| TTL |
|
|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| RDLENGTH
|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
/ RDATA /
/
/
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
NAME is the domain
name u specified in the request.
TYPE is a type code, that specifies the type
in the RDATA section
the most important type codes are :
NAME
VALUE MEANING
A 1 a host address
NS 2 an authoritative name
server
MD 3 a mail destination (Obsolete - use MX)
MF 4 a mail forwarder
(Obsolete - use MX)
CNAME 5 the canonical name for an alias
SOA 6 marks
the start of a zone of authority
for a more detailed list of Qtypes, i
refer to RFC 1035
CLASS is always 1 if it's an internet packet (for all
class values, see
rfc1035)
RDLENGTH is the length of the RDATA
section
RDATA is the data section of the RR. there are many possible
RDATA data
formats, but in most cases, RDATA is the 4 octet IP address you
asked for.
Another format you'll need for more complex operations (like mail
servers),
is the WKS RDATA format. I refer to RFC1035 for that. The format of
RDATA
depends on the value of TYPE
* file formats.
If you make
a DNS daemon, you could store your information in every possible
file format,
like DBF or other database formats, but in rfc 1035 a special
text file
format is developed for domain info. (the master file format).
A master
file consist of lines, separated by a CR-LF sequence. Usually,
the file
starts with this:
$ORIGIN kervel.dyn.ml.org ;this line says the server is
running on kervel....
$INCLUDE m2.txt mail ;this line specifies the file
m2.txt has all the entries
;for mail.kervel.dyn.ml.org
So: each line
can has a comment string (begins with a ;), the comment string
ends at the
end of the line.
$ORIGIN specifies the domain where the name deamon is
running on.
$INCLUDE loads another file into a subdomain
Parentheses are
used to split a line in multiple lines, within parentheses
CR-LF's don't mean
the end of the line, only the end of the comment string.
Then the
hosts/mailboxes,... are specified like this:
[<domain-name>]
<rr>
domain-name : optional : if not set, the domain name is the
domain of the
master file, if set, the server uses the domain name specified,
without
looking for the domain name of the master file.
-> special
characters, like a ".", are noted like this: '\.', to avoid
conflicts. So
altavista.com is altavista\.com
(stolen from rfc 1035)
@ A free
standing @ is used to denote the current origin.
\X where X is any character
other than a digit (0-9), is
used to quote that character so that its special
meaning
does not apply. For example, "\." can be used to place
a dot
character in a label.
\DDD where each D is a digit is the octet corresponding
to
the decimal number described by DDD. The resulting
octet is assumed to
be text and is not checked for
special meaning.
( ) Parentheses are used
to group data that crosses a line
boundary. In effect, line terminations are
not
recognized within parentheses.
; Semicolon is used to start a comment;
the remainder of
the line is ignored.
rr : [<ttl>]
[<class>] <type> <rdata>
ttl and class are used in the
sent RR's, and are optional.
type and rdata are used in the RR to send.
A
sample master file: (stolen from rfc1035)
@ IN SOA VENERA Action\.domains
(
20 ; SERIAL
7200 ; REFRESH
600 ; RETRY
3600000; EXPIRE
60) ;
MINIMUM
NS A.ISI.EDU.
NS VENERA
NS VAXA
MX 10 VENERA
MX 20
VAXA
A A 26.3.0.103
VENERA A 10.1.0.52
A 128.9.0.32
VAXA A
10.2.0.27
A 128.9.0.33
$INCLUDE
<SUBSYS>ISI-MAILBOXES.TXT
Where the file
<SUBSYS>ISI-MAILBOXES.TXT is:
MOE MB A.ISI.EDU.
LARRY MB
A.ISI.EDU.
CURLEY MB A.ISI.EDU.
STOOGES MG MOE
MG LARRY
MG
CURLEY
* to be continued *