Forum Discussion

Josh_Hildebran1's avatar
Josh_Hildebran1
Icon for Nimbostratus rankNimbostratus
Feb 04, 2013

GTM split zone DNS responses - iRule

 

I've just implemented GTM.. we have a split dns zone.. internal IPs for our intranet, and external IPs for our external folks. I consider that pretty standard. Oddly, F5 doesn't appear to have any simple method of continuing my split-zone practice when it comes to wide-IPs in the GTM world..

 

 

The best I've been able to come up with is an LTM iRule that I place on the LTM virtual server that listens to udp/53 for GTM name serving.. Below is the iRule (I apologize, I didn't see a "code" tag in this editor)..

 

 

Essentially, this looks at DNS responses from GTM.. if the client IP is within the private IP range (RFC1918, which is simply a data group), then it does a lookup in another data group (GTM_internal_translation) that will allow the iRule to swap out the external wide IP with the internal version. This does require that I have a one-to-one mapping predefined in the GTM_internal_translation data group.

 

 

My question to the iRule gawds is two fold.. 1) Is this insane? i.e. Is there an easier way? 2) How can this method be optimized?

 

I was initially thinking I'd do a GTM iRule, but I couldn't find the functions that were compatible in GTM iRules to pull this off.. but it certainly seems like a better place to do the iRule.. did I just miss the functions to look at the DNS response within GTM iRules?

 

 

Thank you kindly!

 

 

when DNS_RESPONSE {

 

if { [class match [IP::client_addr] equals RFC1918] } {

 

set response [split [DNS::answer] ]

 

set request [ lindex $response 4 ]

 

log local0. "Alert: $request requested"

 

if { [class match $request equals GTM_internal_translation ] } {

 

set answer [class match -value -- $request equals GTM_internal_translation ]

 

log local0. "Alert: $answer answered"

 

set ttl [DNS::ttl [DNS::answer]]

 

DNS::answer clear

 

DNS::answer insert "[DNS::question name]. $ttl [DNS::question class] [DNS::question type] $answer"

 

 

}

 

}

 

}

 

3 Replies

  • This is how it's done:

     

    http://support.f5.com/kb/en-us/solutions/public/14000/400/sol14421.html

     

  • So the solution article is misleading/incomplete in my opinion...

     

    If you want to use topology at wide IP level to serve internal clients and external clients different IPs for the same WIP - what you need to do is create the RFC_1918 list or list of your internal LDNS and then create a record for each POOL that you are using:

     

    1. Region is Internal_LDNS | Pool is internal-www.example.com-pool
    2. Region is not Internal_LDNS | Pool is external-www.example.com-pool

    So each WIP has 2 pools - 1 internal and 1 external - and uses topology, and the pools then use global availability or whatever.

     

    This is if there is no address translation - I haven't tried with address translation - perhaps the article's solution only works if you are using address translation....

     

  • I wanted to avoid cluttering up our GTM with a bunch of internal pools, so I ended up creating an iRule for each WIP. We have active/active data centers. One data center has a public range of 100.100.100.x/24 that NATs to a private range of 172.100.100.x/24, the other has a public range of 200.200.200.x/24 that NATs to a private range of 10.200.200.x/24. When the GTM receives a query from a private IP (defined in Topology > Regions), the iRule returns the internal IP (LTM VIP) after the GTM has made the LB decision (chosen the "up" pool member). The iRule has been working in production for close to a year now with no issues. It could probably be written more efficiently but I haven't had the chance to revisit it yet.

    when LB_SELECTED {
      if { ([matchregion ldns private-ranges]) && ([LB::server addr] starts_with "100.100.100.") }  {
        host 172.100.100.5
      } elseif { ([matchregion ldns private-ranges]) && ([LB::server addr] starts_with "200.200.200.") } {
        host 10.200.200.36
      }
    }