Forum Discussion

Drew_Berendts_2's avatar
Drew_Berendts_2
Icon for Altostratus rankAltostratus
Dec 11, 2006

DNS Hostname Parsing iRule

Folks:

 

 

I wanted to post a set of iRule code that I and a couple co-workers have been working on. The intent here is to share some code in case someone else can benefit from it.

 

 

My company uses a LTM to front a couple different sets of DNS servers. The below iRule is applied to a UDP/53 virtual server on the LTM. The iRule parses the hostname on the incoming DNS query and can then be used for any number of different things, such as forwarding the DNS query to one pool or another depending on the hostname that is being looked up by the client.

 

 

The original code for this iRule was based on a couple similar postings that were found on DevCentral. The main problem I ran into when trying to use the iRule code from the original postings was that the hostname would not always be returned with the periods in the FQDN in the proper space. This problem was mainly found when a hostname used 8 characters in one of the sections of the FQDN. The problem is that the number "8" is returned as a backspace character in binary and I would thus lose a character in the final output of the FQDN.

 

 

Sorry if the below iRule is somewhat improperly formatted due to the width restrictions of the input screen while I post this message. I have attached an ASCII version of the iRule so folks can review the original formatting if required. The sample code is as follows:

 

 

 

 

when CLIENT_ACCEPTED {

 

 

extract QNAME from QUESTION header

 

$i is a sanity check so this logic won't spin on invalid QNAMEs

 

set i 0

 

 

initialize our position in the QNAME parsing and the text QNAME

 

set offset 12

 

set length 1

 

set endlength 1

 

set name ""

 

 

/extract QNAME from QUESTION header

 

while {$length > 0 && $i < 10} {

 

length contains the first part length

 

binary scan [string range [UDP::payload] $offset $offset]] c foo

 

make the length an unsigned integer

 

set length [expr $foo & 0xff]

 

 

if {$length > 0}

 

{

 

grab a part and put it in our text QNAME section

 

append name [string range [UDP::payload] [expr $offset + 1] [expr $offset + $length]]

 

 

Watch the DNS QNAME get built during the loop. Remove the following line for production use.

 

log local0.info "BUILDING DNS NAME: [IP::client_addr] queried $name offset $offset length $length"

 

 

grab a part and put it in our text QNAME section

 

set offset [expr $offset + $length +1]

 

 

endlength contains the Last part length

 

binary scan [string range [UDP::payload] $offset $offset]] c foo

 

make the length an unsigned integer

 

set endlength [expr $foo & 0xff]

 

 

if { $endlength > 0} {

 

put a dot between parts like a normal DNS name

 

append name "." }

 

 

incr i

 

}

 

}

 

/extract QNAME from QUESTION header

 

 

Input the required action here, where "$name" is the variable that is reviewed for decision making.

 

Sample action would be a pool statement. The below log statement should be removed for production use.

 

 

log local0.info "FINAL DNS NAME: [IP::client_addr] queried $name"

 

}

 

 

 

Hope this material can be of benefit to someone. Thanks to the original posters for their hard work. The above code is simply a fine tuning of their original material.

1 Reply

  • Thanks for the effort, and for building community! Could you post to the codeshare section of DevCentral?

     

     

    For the URL, Click here

     

     

    Again, thanks for your contribution!