Disable DNS Express to allow recursion of a delegated sub-domain

Problem this snippet solves:

If you are using GTM to act both a authoritative slave with DNS Express and as a recursive cache, recursion will not work if a request is made for a delegated sub-domain if the parent domain exists in DNS Express. i.e. domain.com exists in DNS Express but has delegated the dev.domain.com sub-domain to a different set of name server. Any request to dev.domain.com will just get a referral rather than being recursed. This is because of the order of operations in GTM, https://support.f5.com/kb/en-us/solutions/public/14000/500/sol14510.html. Recursion is the very last process that could happen and since DNS Express makes an authoritative referral response no recursion will occur.

How to use this snippet:

To use this your listener and corresponding DNS profile need to have DNS Express configured and recursion enabled(cache). Then the iRule just needs to be attached to the listener.

Code :

when DNS_REQUEST {
#query DNS Express to look for a sub-domain delegation
set rrr [DNS::query dnsx [DNS::question name] [DNS::question type]]
#evaluate if the queried zone is defined in DNS Express
#empty response indicates DNS Express does not have the requested domain
#so we should exit and continue to recursion
if {$rrr equals "{} {} {}"}{return}
#check if DNS Express response is a delegated sub-domain referral
if { [lindex $rrr 0] equals "" && [DNS::type [lindex [lindex $rrr 1] 0]] equals "NS"} {
#no ANSWER was returned AND AUTHORITY is an NS record(not a SOA)
#this is a referral so we should disble DNS Express to allow for the subdomain to be recursed
DNS::disable dnsx
}
}

Tested this on version:

11.6
Published May 25, 2016
Version 1.0
  • Hi Brad, I have this exact issue. :) I am testing using version 12.1.0. It doesn't appear that the irule is working. I set my logs to debug, but nothing helpful. I have you tested the irule on this version?

     

  • I just verified this works all the way through 12.1.1, what does you listener and dns profile look like? Does recursion work for all other domains?

     

  • I got it to work, but need to add additional functionality.

    Is it possible to add additional conditions to forward queries based on client ip to a specific dns pool after we have performed the recursive query for NS records of our DNS Express Zones?

    I can split this Irule into two parts (DNS Express Recursive Query Fix) and (Route based on source IP) independently. When I combine the irules it breaks. I have a feeling it has to do with the order in which the F5 processes the traffic. (CLIENT_ACCEPT before DNS_REQUEST)

    `when DNS_REQUEST {
        query DNS Express to look for a sub-domain delegation
        set rrr [DNS::query dnsx [DNS::question name] [DNS::question type]]
        evaluate if the queried zone is defined in DNS Express
        empty response indicates DNS Express does not have the requested domain
        check if DNS Express response is a delegated sub-domain referral
        if { [lindex $rrr 0] equals "" && [DNS::type [lindex [lindex $rrr 1] 0]] equals "NS"} {
        log local0.debug "ns record detected"
            no ANSWER was returned AND AUTHORITY is an NS record(not a SOA)
            this is a referral so we should disble DNS Express to allow for the subdomain to be recursed
            DNS::disable dnsx
            log local0.debug "Subdomain"
        } elseif { [IP::addr [IP::client_addr] equals 192.168.0.0/24] } {
            pool /Common/ServerResolver
            log local0.debug "ServerResolver"
            return
        } else {
            pool /Common/UserResolver
            log local0.debug "UserResolver"
            return
        }
    }`
    
  • Ok, we got the irule working with these modifications.

    when DNS_REQUEST {
    
      set rrr [DNS::query dnsx [DNS::question name] [DNS::question type]]
    
      set rname [lindex $rrr 0]
      set rtype [DNS::type [lindex $rrr 1]]
    
      log local0.debug "client=[IP::client_addr] name=$rname type=$rtype"
    
      if { $rname equals "" && $rtype equals "NS"} {
    
        log local0.debug "ns record detected"
        DNS::disable dnsx
    
      } elseif { [IP::addr [IP::client_addr] equals 192.168.0.0/24] } {
    
          pool /Common/ServerResolver
          log local0.debug "ServerResolver"
          return
    
      } else {
    
          pool /Common/UserResolver
          log local0.debug "UserResolver"
          return
    
      }
    
    
    }
    
  • Hey Guys,

    Glad I found this thread, I have the same issue. I have a zone that is created via BIND and I configured a DNS Express for that zone (test.com for example). And within that BIND config I have a delegation for security.test.com going to amazon DNS servers. I tried this irule but it looks like it's not working. my version is 14.1.4

    Thanks you! Hope you guys can help me. Ive been dealing for this issue for 6 months now 😄