For more information regarding the security incident at F5, the actions we are taking to address it, and our ongoing efforts to protect our customers, click here.

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

16 Comments