Showing results for 
Search instead for 
Did you mean: 

libDNS.rts: Interrogating and managing DNS traffic in Stingray

 UPDATE January 2015: libDNS version 2.1 released!

The new release is backward-compatible with previous releases and includes the following bug fixes:

  • Fixed multiple bugs in parsing of DNS records


The libDNS.rts library (written by Matthew Geldert and enhanced by Matthias Scheler) attached below provides a means to interrogate and modify DNS traffic from a TrafficScript rule, and to respond directly to DNS request when desired.


You can use it to:



Note: This library allows you to inspect and modify DNS traffic as it is balanced by Stingray.  If you want to issue DNS requests from Stingray, check out the net.dns.resolveHost() and net.dns.resolveIP() TrafficScript functions for this purpose.




This rule can be used when Stingray receives DNS lookups (UDP or TCP) using a Virtual Server, and optionally uses a pool to forward these requests to a real DNS server:



Typically, a listen IP addresses of the Stingray will be published as the NS record for a subdomain so that clients explicitly direct DNS lookups to the Stingray device, although you can use Stingray software in a transparent mode and intercept DNS lookups that are routed through Stingray using the iptables configuration described in Transparent Load Balancing with Stingray Traffic Manager.





Step 1:


Configure Stingray with a virtual server listening on port 53; you can use the 'discard' pool to get started:



If you use 'dig' to send a DNS request to that virtual server (listening on in this case), you won't get a response because the virtual server will discard all requests:


$ dig @

; <<>> DiG 9.8.3-P1 <<>> @

; (1 server found)

;; global options: +cmd

;; connection timed out; no servers could be reached


Step 2:


Create a new rule named libDNS.rts using the attached TrafficScript Source:


DNS3.pngThis rule is used as a library, so you don't need to associate it with a Virtual Server.


Then associate the following request rule with your virtual server:


import libDNS.rts as dns;

$request = request.get();

$packet = dns.convertRawDataToObject($request, "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" ) {


} "DNS request: " . lang.dump( $packet ) );

$host = dns.getQuestion( $packet )["host"];

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

$packet["qr"] = 1; "DNS response: " . lang.dump( $packet ) );

request.sendResponse( dns.convertObjectToRawData($packet, "udp"));


This request rule will catch all DNS requests and respond directly with a CNAME directing the client to look up '' instead:


$ dig @

; <<>> DiG 9.8.3-P1 <<>> @

; (1 server found)

;; global options: +cmd

;; Got answer:

;; ->>HEADER<





This DNS library provides a set of helper functions to query and modify DNS packets.  Internally, a decoded DNS packet is represented as a TrafficScript datastructure and when you are writing and debugging rules, it may be useful to use lang.dump( $packet ) ) as in the rule above to help understand the internal structures.


Create a new DNS packet


$packet = dns.newDnsObject(); lang.dump( $packet ) );


Creates a data structure model of a DNS request/response packet. The default flags are set for an A record lookup. Returns the internal hash data structure used for the DNS packet.


Set the question in a DNS packet


$packet = dns.setQuestion( $packet, $host, $type, $class );


Sets the question in a data structure representation of a DNS packet.


  • $packet - the packet data structure to manipulate.
  • $host - the host to lookup.
  • $type - the type of RR to request.


Returns the modified packet data structure, or -1 if the type is unknown.



Get the question in the DNS packet


$q = dns.getQuestion( $packet );

$host = $q["host"];

$type = $q["type"];

$class = $q["class"];


Gets the question from a data structure representing a DNS request/response.  Returns a hash of the host and type in the data structure's question section.


Add an answer to the DNS packet


$packet = dns.addResponse($packet, $section, $name, $host, $type, $class, $ttl, $additional);


Adds an answer to the specified RR section:


  • $packet - the packet data structure to manipulate.
  • $section - name of the section ("answer", "authority" or "additional") to add the answer to
  • $name, $host, $type, $class, $ttl, $additional - the answer data


Returns the modified packet data structure.


Remove an answer from the DNS packet


$packet = dns.removeResponse( $packet, $section, $answer ); while( $packet["additionalcount"] > 0 ) { $packet = dns.removeResponse( $packet, "additional", 0); }


Removes an answer from the specified RR section.


  • $packet - the packet data structure to manipulate.
  • $section - name of the section ("answer", "authority" or "additional") to remove the entry from
  • $answer - the array position of the answer to remove (0 removes the first).


Returns the modified packet data structure, or -1 if the specified array key is out of range.


Convert the datastructure packet object to a raw packet


$data = dns.convertObjectToRawData( $packet, $protocol ); request.sendResponse( $data );


Converts a data structure into the raw data suitable to send in a DNS request or response.


  • $packet - data structure to convert.
  • $protocol - transport protocol of data ("udp" or "tcp").


Returns the raw packet data.



Convert a raw packet to  an internal datastructure object


$data = request.get(); $packet = dns.convertRawDatatoObject( $data, $protocol );


Converts a raw DNS request/response to a manipulatable data structure.


  • $data - raw DNS packet
  • $protocol - transport protocol of data ("udp" or "tcp")


Returns trafficscript data structure (hash).





Kudos to Matthew Geldert, original author of this library, and Matthias Scheler, author of version 2.0.

Version history
Revision #:
1 of 1
Last update:
‎04-10-2013 07:35:AM
Updated by:
Labels (1)

The library has been updated to v1.2, adding a fix to handle DNS requests that contain Answer, Authority or Additional sections.  These are generated by some Exchange servers, and by versions of dig >= 9.9.1.