cancel
Showing results for 
Search instead for 
Did you mean: 

HowTo: Implement a simple DNS resolver using libDNS.rts

This article uses the libDNS.rts trafficscript library as described in libDNS.rts: Interrogating and managing DNS traffic in Stingray.

 

In this example, we intercept DNS requests and respond directly for known A records.

 

The request rule

 

import libDNS.rts as dns;

# Map domain names to lists of IP addresses they should resolve to

$ipAddresses = [

   "dev1.ha.company.internal." => [ "10.1.1.1", "10.2.1.1" ],

   "dev2.ha.company.internal." => [ "10.1.1.2", "10.2.1.2" ]

];

$packet = dns.convertRawDataToObject( request.get(), "udp" );

# Ignore unparsable packets and query responses to avoid

# attacks like the one described in CVE-2004-0789.

if( hash.count( $packet ) == 0 || $packet["qr"] == "1" ) {

   break;

}

$host = $packet["question"]["host"];


if( hash.contains( $ipAddresses, $host )) {

   foreach( $ip in $ipAddresses[$host] ) {

      $packet = dns.addResponse($packet, "answer", $host, $ip, "A", "IN", "60", []);

   }

   $packet["aa"] = "1"; # Make the answer authorative

} else {

   $packet["rcode"] = "0011"; # Set NXDOMAIN error

}

$packet["qr"] = "1"; # Changes the packet to a response

$packet["ra"] = "1"; # Pretend that we support recursion

request.sendResponse( dns.convertObjectToRawData($packet, "udp"));
Version history
Revision #:
1 of 1
Last update:
‎04-10-2013 08:30:AM
Updated by:
 
Labels (1)
Comments
kalipinde

Hi Paul,

 

 This looks great and I'm currently testing this out as it might help me out with a geolocating issue.

 

 Is there a way to use libDNS.rt to send all DNS requests back to the client using one DNS server pool (my internal servers) but if the client is requesting a specific domain name such as "example.differentdomain.com" that we can send this DNS request to a different server pool (a public DNS server)?

 

Regards.

 

Kal.

 

 

mbodding

Hi Kal,

 

Sure that's quite simple. You would just parse the packet and pull out the host, check to see if the request is in a domain which should be handled by your internal servers, and if not pool.use() to send the packout out to a public resolver. Something like:

 

import libDNS.rts as dns;

$mydomains = [ "foo.com", "bar.net"];

$packet = dns.convertRawDataToObject( request.get(), "udp" );
if( hash.count( $packet ) == 0 || $packet["qr"] == "1" ) {
   break;
}
$host = $packet["question"]["host"];

$local=0;
foreach ( $name in $mydomains ) {
  if (string.endswith($host, $name)) {
    $local=1;
  }
}

if ( $local == 0 ) {
# use public DNS pool.use("public-dns"); }

# fall through to internal DNS pool.

Cheers,

Mark

kalipinde

Hi Mark,

 

 Thank you so much for the quick response. I will test it out!

 

Regards,

 

Kal.