Forum Discussion

Drew_Berendts_2's avatar
Drew_Berendts_2
Icon for Altostratus rankAltostratus
Oct 31, 2006

LTM DNS Selective SNAT

I have a LTM running OS 9.2.3 that fronts two separate pools, one pool of GTM nodes & another of 3DNS nodes. I have a virtual server running on UDP/53 that accepts incoming DNS queries on the LTM and then forwards the incoming traffic to either the 3DNS or GTM pool based on the hostname queried by the external client.

 

 

The below iRule is something that I pieced together based on some homework here on DevCentral (thanks much to a1l0s2k9 & yangmfbj for their hard work on the original code). The code works almost flawlessly except for queries coming in from a set of upstream servers in the address block of 10.1.64.0/24. I find that queries coming in from these DNS servers are always sent to the default 3DNS pool, regardless of what hostname is queried. I have tinkered w/ this script a great deal to work around the problem, even putting in an if statement at the very top of the iRule that would forward all traffic from 10.1.64.0/24 to the GTM pool. Still no luck. Anyone have any ideas? Perhaps something in the below binary code that would cause a hiccup w/ this? I ask only due to the fact that queries from all other upstream DNS servers work. I have looked at the queries coming from the 10.1.64.0/24 servers in Ethereal and they perfectly match other DNS servers that are working correctly. I can also watch the DNS queries from these servers on the LTM via tcpdump are they are recognized correctly as DNS queries. They simply won't follow the given pool rules. I am at a loss on this point. Thx to anyone who might have an idea if perhaps something in the below iRule code could be causing me issues.

 

 

 

when CLIENT_ACCEPTED {

 

 

extract QNAME from QUESTION header

 

check rcode

 

binary scan [ string range [UDP::payload] 2 3 ] S sflags

 

set rcode [expr $sflags & 0x000f]

 

 

skip the DNS header, jump to the QNAME part of first QUESTION

 

byte contains the first part length

 

binary scan [string range [UDP::payload] 12 13 ] c foo

 

 

make the byte an unsigned integer

 

set byte [expr $foo & 0xff]

 

 

initialize our posisition in the QNAME parsing and the text

 

QNAME

 

set offset 12

 

 

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

 

set i 0

 

 

initialize our posisition in the QNAME parsing and the text

 

QNAME

 

set offset 12

 

set name ""

 

/extract QNAME from QUESTION header

 

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

 

grab a part and put it in our text QNAME section

 

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

 

 

put a dot between parts like a normal DNS name

 

append name "."

 

 

grab a part and put it in our text QNAME section

 

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

 

 

grab the length of the next part, and make it an unsigned

 

integer

 

set byte [string range [UDP::payload] $offset [expr $offset + 1]]

 

binary scan $byte c foo

 

set byte [expr $foo & 0xff]

 

incr i

 

}

 

/extract QNAME from QUESTION header

 

 

if { $name contains "fred" } {

 

pool GTM.Pool

 

} else {

 

pool 3DNS.Pool

 

}

 

}

 

 

Regards,

 

 

Drew B.

1 Reply

  • Without being able to test this, I'd suggest adding logging to the rule to see where you're getting unexpected results. Try posting the logging output if you have questions.

     

     

    Aaron