BIG-IP DNS Forwarder Support via iRule

Problem this snippet solves:

The BIG-IP DNS Product does not currently (without named) support DNS forwarders. Some customers wish to avoid exposing named but want forwarder support.

How to use this snippet:

Apply this iRule to your BIG-IP DNS Listener and configure a datagroup

Code :

when DNS_REQUEST {
    set forwarded 0
    if {[class match [DNS::question name] ends_with forwarded_zones]}{
        set count [table incr [class match -element [DNS::question name] ends_with forwarded_zones]]
        log "Count for [class match -element [DNS::question name] ends_with forwarded_zones]]: $count"
        DNS::disable dns-express cache bind gtm
        set forwarders [class match -value [DNS::question name] ends_with forwarded_zones]
        log "Query question: [DNS::question name] Type: [DNS::question type] - Forwarders: $forwarders"
        set forwarder_list [split $forwarders]
        set forwarder [lindex $forwarder_list [expr $count % [llength $forwarder_list]]]
        log "Forwarder: $forwarder"
        translate address enable
        snat automap
        node $forwarder
    }
}

Tested this on version:

13.0
Published Jul 24, 2020
Version 1.0
  • good catch, that variable was reserved for future use and I didn't even put the code in to set it to 1 if we forwarded. The expectation is that this code might be combined with other code that is hooked up to the DNS_REQUEST event.

  • I like how you are toggling between forwarders. This is a much better idea than I came up with for a similar solution.

     

    What is the variable 'forwarded' used for?

  • note that the iRule will rotate forwarding queries between the IPs listed in the datagroup, but it doesn't do anything to track whether or not there is a response and retry it to the other server. The expectation is that the client submitting the request to the listener would resubmit the query. It should be possible to implement some timeout/retry logic in the iRule, but for now, that is to be completed/explored.

  • Example Datagroup:

    ltm data-group internal forwarded_zones {

    records {

    f5.com {

    data "1.0.0.1 1.1.1.1"

    }

    }

    type string

    }