on 08-Feb-2023 10:46
An iRule based solution for GSLB with Split DNS (that is, one answer for internal users, one for external users).
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.
Config required:
tmsh create gtm region private region-members add { subnet 10.0.0.0/8 subnet 192.168.0.0/16 }
# 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
when DNS_REQUEST {
# 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
return
}
# 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"
drop
return
}
# internal client - search for internal pool
set foundpool [lsearch -inline $pools *$intpoolstr*]
if { $foundpool != "" } {
pool $foundpool
if { $debug } { log local0. "Using internal pool $foundpool" }
return
}
# 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"
}