Implementing Client Subnet DNS Requests

Problem this snippet solves:

Update 2018-10-23: As of BIG-IP DNS 14.0 there is now a checkbox feature for edns-client-subnet. Please see: Using Client Subnet in DNS Requests. The following is still useful if you want to customize your responses.

Original post:

Using an iRule and edns-client-subnet (ECS) we can improve the accuracy of F5 GTM’s topology load balancing.

How to use this snippet:

There are two different iRules. One is an LTM iRule and the second is a GTM iRule. These should be deployed separately.

Code :

#
# LTM iRule
#
# comply with draft to respond with ECS  
when DNS_REQUEST {  
  if { [DNS::edns0 exists] &! [catch { DNS::edns0 subnet address }] } {  
    set ecs_address [DNS::edns0 subnet address]  
    set ecs_source [DNS::edns0 subnet source]  
    set ecs_scope [DNS::edns0 subnet scope]  
    log local0. "Received EDNS request from [IP::client_addr]:$ecs_address/$ecs_source/$ecs_scope"  
  }  
}  
when DNS_RESPONSE {  
  if { [info exists ecs_address] } {  
  DNS::edns0 subnet address $ecs_address  
  DNS::edns0 subnet source $ecs_source  
  #DNS::edns0 subnet scope $ecs_scope  
  # hardcode the desired scope to be /24, not sure this is OK  
  DNS::edns0 subnet scope 24  
  }  
}
#
# GTM iRule
#  
when DNS_REQUEST {  
  set ldns [IP::client_addr]  
  log local0. "LDNS LOC: $ldns [whereis $ldns]"  
  
  if { [DNS::edns0 exists] &! [catch { DNS::edns0 subnet address }] } {  
    set gtm_ecs_address [DNS::edns0 subnet address]  
    set gtm_ecs_source [DNS::edns0 subnet source]  
    set gtm_ecs_scope [DNS::edns0 subnet scope]  
    set ldns  $gtm_ecs_address  
    log local0. "ECS LOC: $gtm_ecs_address [whereis $ldns]"  
  }  
  set loc [whereis $ldns]  
  
  if { $loc contains "NA" } {  
    log local0. "NA"  
  }  
  elseif { $loc contains "AS" } {  
    log local0. "Asia"  
  }  
  elseif { $loc contains "EU" } {  
    log local0. "Europe"  
  } else {  
    log local0. "All other"  
  }  
  
}

Tested this on version:

11.6
Published Jun 16, 2015
Version 1.0