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.
- DevCentral Article: Implementing Client Subnet DNS Requests
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- Eric_ChenEmployee
Matt, if you have a second LTM/GTM device it is possible to SNAT the connection to match the ecs_address. You end up with something like:
when DNS_REQUEST { ... snat $ecs_address ... }
This works by using a feature of LTM/GTM of auto last hop to route the snat'd traffic back to the original device that received the request. It assumes that both LTM/GTM devices are L2 adjacent.
The config is
Device 1: LTM listener with DNS profile/LTM iRule performing SNAT. Pool is GTM listener on Device 2. Device 2: GTM listener with DNS profile (vanilla GTM)
Traffic flow:
Internet (LDNS IP) -> Device 1 (SNAT to ECS IP) -> Device 2 -> Device 1 -> Internet
Be warned that you are trusting the ECS records to intentionally spoof traffic to Device 2. I have only tested this in a lab environment and have noted that it does some weird things to the EDNS records that get passed along to Device 2.
- mchaasNimbostratus
Hi,
is there a way to tamper with the DNS response based on this information? We are running GTM. When the listener is receiving a DNS query, I would like to decide which virtual server out of the selected pool is used and posted back in the dns response depending on both location (based on the EDNS information) AND availability of the respective resource.
So, ideally, in analogy to the GSLB "Topology Record Builder" settings, I would like to set the datacenter information, but not based on the Client-IP in the Layer3 Header, but based on the EDNS client information, as shown in the code snippet.
Is this possible? Thanks!
Regards, Matt
- bodra_143113Historic F5 Accountthe whereis fails due to a bug As a workaround you can force a string interpretation of the IP i.e. set loc [whereis [string tolower $ldns]]
- Chris_G_01_1415NimbostratusDo we know if there is any way to get this working in 11.5.3 or 11.5.4?
- Eric_ChenEmployeeHi, I'm seeing a similar result with using 11.5.3. I agree that the issue appears to be with passing the variable $gtm_ecs_address to whereis and getting back an empty response. When I created the iRule I had tested with 11.6.0, but not with 11.5.3. I'll update the codeshare to reflect that this works 11.6.0 and forward.
- tiny_cloud_ninjHistoric F5 AccountTesting this iRule in TMOS 11.5.3 HF1 without success. It looks as if whereis is not returning a value. on test DNS ./bin/dig/dig @10.1.10.100 record.siterequest.com +client=8.8.8.8 A Dec 20 18:36:53 gtm info tmm1[12620]: Rule /Common/mvpn_EDNS_iRule : LDNS LOC: 10.1.10.222 Dec 20 18:36:53 gtm info tmm1[12620]: Rule /Common/mvpn_EDNS_iRule : ECS LOC: 8.8.8.8 Dec 20 18:36:53 gtm info tmm1[12620]: Rule /Common/mvpn_EDNS_iRule : defualt