Hello, please sign in or register
You are here: Home

DNS message format

Call me nuts but i want to create my own DNS Server (pardon the tautology) using PHP. A Domain Name Server Server fundamentally resolves a domain name into IP addresses.

Whilst the DNS protocol has been addressed painfully innumerably since the dawn of the internet. I feel this deserves one more article, purely for simplistic and self styled interpretation in a language i understand - English.

This PHP script sends DNS queries using PHP pack function to deliver bits and bytes as they are recieved. To understand the binary data sent I am avoiding employing a PHP inbuilt network function.

// This script returns an array of byte values.
// This just introduces a possible DNS query
$udp = true;
$ns1 = "NS15.1AND1.CO.UK";
$dom = "knarly.com";


$a = array(
// 16 bits
	// Create a random two 16 bit sequence.
	str_pad(decbin(rand(0, pow(2,16))), 16, '0', STR_PAD_LEFT), 

// 16 bits
// The next 16bits are flags.
	0, 		// QR: query=0, response=1, 
	'0000', 	// Opcode: (standard query = 0000)
	0,		// AA: used in response
	0,		// TC: Truncation flag (truncated data=1, 
					// might ask again via tcp which is not limited by size??? whats the point in this?), 
	1, 		// RD: Recursion desired
	0,		// RA: Recursion Available
	'000', 		// ?? (zeros)
	'0000',		// RCode: Response codes (set to zero is requests) 

// QDCOUNT: Question count
// 16 bits
// Specifies the number of questions in the Question section of the message.
	str_pad(1, 16, '0', STR_PAD_LEFT), 

// ANCount: Answer Record Count
// 16 bits
// Specifies the number of resource records in the Answer section of the message.
	str_pad(0, 16, '0', STR_PAD_LEFT), 

// NSCount: Authority Record Count
// 16 bits
// Specifies the number of resource records in the Authority section of the message. (“NS” stands for “name server”, of course. J)
	str_pad(0, 16, '0', STR_PAD_LEFT), 

// ARCount: Additional Record Count: 
// 16 bits
// Specifies the number of resource records in the Additional section of the message.
	str_pad(0, 16, '0', STR_PAD_LEFT), 


$h = (binary)'';
foreach( str_split(implode('',$a), 8) as $o )
	$h .= pack('C*', bindec($o));

 * Query
// build the name of the domain we are looking up.
// e.g. [3] w w w [13] x y z i n d u s t r i e s [3] c o m [0]
// Where [13] is one byte and not two.
// The numbers say how many characters follow. The last one must be 0.

$q = (binary)'';
foreach( explode( '.', $dom.'.') as $o )
	$q .= pack( "C", strlen( $o ) ).( $o!='' ? pack('a*',$o) : NULL );

// Query Type (2 bytes) | Query class (2 bytes)
// (1=>'A',2=>'NS',5=>'CNAME',5=>'SOA',12=>'PTR',13=?'HINFO',15=>'MX',16=>'TXT');
$q .= pack( "C", bindec('00000000') );
$q .= pack( "C", bindec('00000001') );
$q .= pack( "C", bindec('00000000') );
$q .= pack( "C", bindec('00000001') );

 * Connect and send

if( !( $s = fsockopen(($udp?'udp://':NULL).$ns1, 53, ${''}, ${''}, 5) ) )
	print "Failed Connected to $ns1"; 

// Wait for content, i think this is the default anyway
socket_set_blocking( $s, true );

// If this is TCP then the first value must be the length... not sure why tcp is so picky?
fwrite( $s, (!$udp? pack( 'n', strlen($h.$q) ) : NULL ).$h.$q );

// Get response
print_r( unpack( 'C*', fread( $s, 1024 ) ) );



In this example i have created binary data and sent it to a DNS. The result should be an array of data containing integers for each byte response.

To decode the message requires understanding the message structure which begins with a similar header to the one we started with.

To run this as a server obviously requires a bit more work. There is a nice article at http://devzone.zend.com/article/1086-Writing-Socket-Servers-in-PHP Which i hope to investigate shortly.


To see interpretations of the byte string sent: i recommend http://www.netfor2.com/dns.htm as a good heuristic study. A good theoretical study

As always - RFC's are a comprehensive source of information http://www.faqs.org/rfcs/rfc1035.html (Domain names implementaion and specification)

Whilst reasearching this exercise i found an interesting project


I cried when i saw the cruft in PHPResolver class written by Moriyoshi Koizumi. And urge no one to ever write another convoluted object instance nightmare. But it helped me to crawl i guess. The equally appalling verbosity of PHP_NET in the pear archive is better spent compounding a guide of stoates and weasles gentle countenance. Only to brutally hospitalized by aforementioned pugnacious cretin.


Any objection to adding this post to my blog, highonphp.com?
Created 25/01/12
“I canada goose outlet think it doesn’t swarovski jewelry bode very
Created 21/01/16
The michael--kors.org.uk next ralph lauren outlet day patriots jersey Mrs
Created 01/03/16
Tyrion 5c cases watched her ray ban sunglasses read. His timber...
Created 18/04/16
Bond grinned. pandora-bracciali.it "We bcbgmax.in.net only chaussure...
Created 15/06/16
This hilfiger outlet time swarovski jewelry something really timberland outlet strange, ...
Created 30/06/16
ninest123 One canada goose pas cher gucci outlet thing
Created 21/07/16

Prove you are not a robot

To prove you are not a robot, please type in the six character code you see in the picture below
Security confirmation codeI can't see this!
Email never shown*
Home Page


Andrew Dodson
Since:Feb 2007

Comment | flag


Bookmark and Share