GSLB Split DNS by iRule

Code is community submitted, community supported, and recognized as ‘Use At Your Own Risk’.

Short Description

An iRule based solution for GSLB with Split DNS (that is,  one answer for internal users,  one for external users).  

Problem solved by this Code Snippet

Split DNS GSLB can be achieved iRule-free using Topology Records as per AskF5 K14421.   However,  using Topology load balancing requires a Topology Record per pool, so two per Wide IP.  This iRule instead selects pools based on pool naming convention, so removes the need for Topology Records.   

If the iRule is attached to a Wide IP which does not have a pool named suitably for the location of the client, we fallback to dropping queries from external clients.  Internal clients will get normal GSLB behaviour.

How to use this Code Snippet

Config required:

  • One Topology-Region object defining ‘internal’ client IPs  
tmsh create gtm region private region-members add { subnet  subnet }
  • Wide IP(s) with this iRule attached,  these should have an internal and an external pool as the Wide IP members.   The LB algorithm for the Wide IP can be anything. 
  • For the pools,  whatever LB Method your application requires, e.g. Least Connections.  You will probably want a Fallback Load Balancing Method configured on the pools, either Fallback IP or Drop Packet, to catch the scenario where all the pool members are down.  Otherwise,  GSLB will choose from the alternate pool,  leaking internal IPs to external clients.
  • Configure the iRule to reflect the naming convention of pools and the name of the Region object. The pool naming requires that pools for external clients includes some fixed string e.g. _EXT_,  and internal clients some other string e.g. _INT_.
  • You can enable debug logging in the iRule either globally or for selected Wide IPs.

Code Snippet Meta Information

  1. Version:  1.0
  2. Coding Language: TCL iRule

Full Code Snippet

# pool_region_select
# attach to Wide IP to modify pool selection behaviour
# for internal clients: select the internal pool (based on name), fallback to regular GSLB
# for external clients: select the external pool (based on name), fallback to drop packet
# internal clients are determined based on a Topology Region object
# logs warnings to /var/log/ltm on fallback so don't attach to Wide IP unless there are internal and external pools configured
# do not use Return to DNS on the pools, as that will expose IPs from both pools in responses; for a fallback when pool members are down, use Fallback IP

# set debug to 1 for global debug logging (no recommended in production)
set debug 0
# add a Wide IP to the debugwideips list to enable debug for specific Wide IP(s)
set debugwideips { /Common/app1.pri /Common/app2.pri }
# set the name of the Topology Region object
set intregion private
# set the string that must be in a Internal pool object name
set intpoolstr _INT_
# set the string that must be in a External pool object name
set extpoolstr _EXT_

# enable debug if Wide IP is selected for debug
if { [lsearch $debugwideips "[wideip name]" ] >= 0 } { set debug 1 }

if { $debug } { log local0. "Client [IP::client_addr] query for [wideip name]" }

# get list of pools for the Wide IP
set pools [pools -list]

# is the client internal based on topology region (error if an issue like no topology region defined)
if { [catch {matchregion [IP::client_addr] $intregion} isinternal] } {
log local0. "ERROR matching internal region $intregion: $isinternal, treating as external"
set isinternal 0

if { $debug } { log local0. "Wide IP [wideip name] has pools: {$pools} ; Is [IP::client_addr] internal? $isinternal " }

if { !($isinternal) } {
# external client - search for external pool
set foundpool [lsearch -inline $pools *$extpoolstr*]
# if we found external pool. use it
if { $foundpool != "" } {
if { $debug } { log local0. "Using external pool $foundpool for client [IP::client_addr] query for [wideip name]" }
pool $foundpool
# there was no external pool, so drop packet
log local0. "WARNING drop packet from external client to [wideip name] as we have no external ($extpoolstr) pool"

# internal client - search for internal pool
set foundpool [lsearch -inline $pools *$intpoolstr*]
if { $foundpool != "" } {
pool $foundpool
if { $debug } { log local0. "Using internal pool $foundpool" }
# there was no internal pool so warn and do nothing
log local0. "WARNING defaulting to regular WideIP GSLB behaviour for internal client to [wideip name] as we have no internal ($intpoolstr) pool"



Published Oct 04, 2022
Version 1.0

Was this article helpful?