Forum Discussion
GTM iRule - cname
Hi all,
I'm trying to test a simple iRule to return a cname for a wide IP. I looked at the cname Wiiki on dev central and my syntax looks correct, however, it is not returning the cname response. Ultimatly this will be used in a more complex iRule but I need to verify this works first.
Here is the simple iRule:
when DNS_REQUEST {
cname "test.test.com"
}
When i do an nslookup all I get in return is the name of the host I queried
Any ideas what I'm missing for this?
Btw, if I substitute the cname command for host it works.
i.e.
when DNS_REQUEST {
host 10.10.10.10
}
18 Replies
- Mohamed_Lrhazi
Altocumulus
There is no RFC for returning a CNAME when the client sends an A query to a root record so i'm unsure if the client will even accept a CNAME in response and act upon it.
I dont know much about this.. but I feel like saying;
Is there any RFC saying any different? Any RFC stating that a DNS query for "root zone" can not be answered with a CNAME? - dstogsdill_2492
Nimbostratus
I was told by my F5 rep that the RFC states that a root record query can only be answered with an A record. The link i posted previously states pretty much the same thing.
Anyways, I was able to come with a solution. Since the application will be hosted within AWS and all i need to do is host the domain I really have no need to check the health of the application. Essentially, i just need to provide DNS resolution and let AWS provide the global load balancing.
I ended writing a simple shell script to lookup the IP's of the AWS Alias, output the IP's to a file and then update an iFile. The iRule then uses the iFile to return the IP as an A record.
This would be much simpler if I could have used the Resolve::Lookup iRule method on the GTM, however, it only seems to be available within the LTM Module.
Anyways, for anyone who is interested here is the script. I initially created the iFile record via the gui so this script just updates the existing iFile.
I use dig to get the IP's. Amazon returns two IP's so I remove the second listed IP. I then have to remove the new line and trailing white spaces before outputting to a file. This is essential as the iRule Host command doesn't like any white spaces. I then issue the TMSH commands to update the iFile.
I have to thank the guys on this post for giving me the syntax to specify a file on the local file system when modifying the iFile. I could not find any documentation on AskF5 for this.
https://devcentral.f5.com/Community/GroupDetails/tabid/1082223/asg/53/aft/2159165/showtab/groupforums/Default.aspx
I will end up rewriting this to return both IP's and error checking but this works for now.
-----------------------------------------------------------------------------------------------
!/bin/bash
dig +short @8.8.8.8 node.amazonaws.com IN A | sed '$d' | tr '\n' ' ' | sed 's/ $//' > /config/scripts/ag_aname.txt
tmsh modify /sys file ifile ag_aname.txt source-path file:/config/scripts/ag_aname.txt
tmsh save /sys config >>/dev/null
---------------------------------------------------------------------------------------------
And here is the iRule
------------------------------------------------------------------------------------------
when DNS_REQUEST {
set ifileContent [ifile get "/Common/ag_aname"]
host $ifileContent
log local0. $ifileContent
unset ifileContent
}
If anyone has a simpler way of doing this I would love to hear it. - gbbaus_104974Historic F5 AccountNot directly answering the thread, but need to repost my EAV posted above (original copy/paste issue.)
Anyway, here is the EAV based on 2 AWS DNS server lookups, to avoid resolver delays if down
Resolve name to IP address
Do a curl against the site to see if it is up .. based on DNS lookup above
* If it is up, then iRule will return CNAME to send client tot he cloud
If curl fails, means the cloud site is down, and then irule will return wideip from GTM pool for internal resorce
==================
!/bin/bash
For Bip-IP v11 use GUI to import EAV
For Big-IP pre v11
Save as /usr/bin/monitors/custom_monitor.bash
or
Save as /config/monitors/custom_monitor.bash
Make executable using chmod 755 custom_monitor.bash
The below arguments are supplied automatically
based on the pool members that the EAV is assigned to
$1 = IP (::ffff:nnn.nnn.nnn.nnn notation or hostname)
$2 = port (decimal, host byte order)
Log debug to /var/log/ltm
Check if a variable named DEBUG exists from the monitor definition
The following must be set in the EAV GUI
DEBUG=0 or 1
RESPONSE_CHECK
FQDN_TO_RESOLVE
DNS_SERVER_1
DNS_SERVER_2
if [ -n "$DEBUG" ]
then
if [ $DEBUG -eq 1 ]; then echo "EAV `basename $0`: \$DEBUG: $DEBUG" | logger -p local0.debug; fi
fi
Remove IPv6/IPv4 compatibility prefix (LTM passes addresses in IPv6 format)
We are not actually using it in this monitor
IP=`echo $1 | sed 's/::ffff://'`
Save the port for use in the shell command
PORT=$2
Check if there is a prior instance of the monitor running
pidfile="/var/run/`basename $0`.$IP.$PORT.pid"
if [ -f $pidfile ]
then
kill -9 `cat $pidfile` > /dev/null 2>&1
echo "EAV `basename $0`: exceeded monitor interval, needed to kill ${IP}:${PORT} with PID `cat $pidfile`" | logger -p local0.error
fi
Add the current PID to the pidfile
echo "$$" > $pidfile
Resolve name to IP address
QUERY_RESULT=$(dig @${DNS_SERVER_1} +time=1 +tries=1 +short ${FQDN_TO_RESOLVE} IN A | head -n1)
if [[ $QUERY_RESULT =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
if [ $DEBUG -eq 1 ]; then echo "EAV `basename $0`: Succeeded for ${MY_FQDN} from ${DNS_SERVER_1}" | logger -p local0.debug; fi
Do a curl against the site to see if it is up .. based on DNS lookup above
curl -fNs ${QUERY_RESULT} --header 'Host: ${FQDN_TO_RESOLVE}' | grep -i "${RESPONSE_CHECK}" 2>&1 > /dev/null
if [ $? -eq 0 ]
then
echo "up"
fi
rm -f $pidfile
else
QUERY_RESULT=$(dig @${DNS_SERVER_2} +time=1 +tries=1 +short ${FQDN_TO_RESOLVE} IN A | head -n1)
if [[ $QUERY_RESULT =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
if [ $DEBUG -eq 1 ]; then echo "EAV `basename $0`: Succeeded for ${MY_FQDN} from ${DNS_SERVER_2}" | logger -p local0.debug; fi
curl -fNs ${QUERY_RESULT} --header 'Host: ${FQDN_TO_RESOLVE}' | grep -i "${RESPONSE_CHECK}" 2>&1 > /dev/null
if [ $? -eq 0 ]
then
echo "up"
fi
rm -f $pidfile
else
rm -f $pidfile
if [ $DEBUG -eq 1 ]; then echo "EAV `basename $0`: Failed for ${MY_FQDN} across all DNS servers ${DNS_SERVER_1} and ${DNS_SERVER_2} and ${DNS_SERVER_3}" | logger -p local0.debug; fi
fi - gbbaus_104974Historic F5 AccountNot directly answering the thread, but need to repost my EAV posted above (original copy/paste issue.)
Anyway, here is the EAV based on 2 AWS DNS server lookups, to avoid resolver delays if down
Resolve name to IP address
Do a curl against the site to see if it is up .. based on DNS lookup above
* If it is up, then iRule will return CNAME to send client tot he cloud
If curl fails, means the cloud site is down, and then irule will return wideip from GTM pool for internal resorce
==================
!/bin/bash
For Bip-IP v11 use GUI to import EAV
For Big-IP pre v11
Save as /usr/bin/monitors/custom_monitor.bash
or
Save as /config/monitors/custom_monitor.bash
Make executable using chmod 755 custom_monitor.bash
The below arguments are supplied automatically
based on the pool members that the EAV is assigned to
$1 = IP (::ffff:nnn.nnn.nnn.nnn notation or hostname)
$2 = port (decimal, host byte order)
Log debug to /var/log/ltm
Check if a variable named DEBUG exists from the monitor definition
The following must be set in the EAV GUI
DEBUG=0 or 1
RESPONSE_CHECK
FQDN_TO_RESOLVE
DNS_SERVER_1
DNS_SERVER_2
if [ -n "$DEBUG" ]
then
if [ $DEBUG -eq 1 ]; then echo "EAV `basename $0`: \$DEBUG: $DEBUG" | logger -p local0.debug; fi
fi
Remove IPv6/IPv4 compatibility prefix (LTM passes addresses in IPv6 format)
We are not actually using it in this monitor
IP=`echo $1 | sed 's/::ffff://'`
Save the port for use in the shell command
PORT=$2
Check if there is a prior instance of the monitor running
pidfile="/var/run/`basename $0`.$IP.$PORT.pid"
if [ -f $pidfile ]
then
kill -9 `cat $pidfile` > /dev/null 2>&1
echo "EAV `basename $0`: exceeded monitor interval, needed to kill ${IP}:${PORT} with PID `cat $pidfile`" | logger -p local0.error
fi
Add the current PID to the pidfile
echo "$$" > $pidfile
Resolve name to IP address
QUERY_RESULT=$(dig @${DNS_SERVER_1} +time=1 +tries=1 +short ${FQDN_TO_RESOLVE} IN A | head -n1)
if [[ $QUERY_RESULT =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
if [ $DEBUG -eq 1 ]; then echo "EAV `basename $0`: Succeeded for ${MY_FQDN} from ${DNS_SERVER_1}" | logger -p local0.debug; fi
Do a curl against the site to see if it is up .. based on DNS lookup above
curl -fNs ${QUERY_RESULT} --header 'Host: ${FQDN_TO_RESOLVE}' | grep -i "${RESPONSE_CHECK}" 2>&1 > /dev/null
if [ $? -eq 0 ]
then
echo "up"
fi
rm -f $pidfile
else
QUERY_RESULT=$(dig @${DNS_SERVER_2} +time=1 +tries=1 +short ${FQDN_TO_RESOLVE} IN A | head -n1)
if [[ $QUERY_RESULT =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
if [ $DEBUG -eq 1 ]; then echo "EAV `basename $0`: Succeeded for ${MY_FQDN} from ${DNS_SERVER_2}" | logger -p local0.debug; fi
curl -fNs ${QUERY_RESULT} --header 'Host: ${FQDN_TO_RESOLVE}' | grep -i "${RESPONSE_CHECK}" 2>&1 > /dev/null
if [ $? -eq 0 ]
then
echo "up"
fi
rm -f $pidfile
else
rm -f $pidfile
if [ $DEBUG -eq 1 ]; then echo "EAV `basename $0`: Failed for ${MY_FQDN} across all DNS servers ${DNS_SERVER_1} and ${DNS_SERVER_2} and ${DNS_SERVER_3}" | logger -p local0.debug; fi
fi - dstogsdill_2492
Nimbostratus
Bump on this.
QUERY_RESULT=$(dig @${DNS_SERVER_1} +time=1 +tries=1 +short ${FQDN_TO_RESOLVE} IN A | head -n1)
Much better than what I was using to parse out the IP address. Thanks! - Mudhen_64776
Nimbostratus
Anyone happen to have duplicated the AWS/EAV/iRule configuration on v12+?
I got it running on v11 but v13 is so very different (and just running an upgrade only brings in the objects, it breaks it completely)...like you can't apply an EAV to a CNAME pool. And if you use an 'A' record pool you can't have a CNAME.
Even in my iRule if I try to tell it to return the CNAME pool it doesn't work - as soon as you use the keyword 'cname' it returns the next entry as the CNAME itself, not the pool. And if you don't use the keyword 'cname' it says it can't find the CNAME pool. lol.
Thx
- Mudhen_64776
Nimbostratus
Nm...got it. Use an 'A' record pool and if it returns 'up' from the EAV have the iRule respond directly with the CNAME, don't have it attempt to point to a pool to return the CNAME. Bazinga.
v13 is a four letter word.
M
- anonomike
Nimbostratus
This is the closest thread I can find to my issue: 13.1.1 and Applications are moving into Azure. All that is supposed to be required is CNAME to Azure's CNAMEs but although this works on the external BIG-IP DNS with ZoneRunner something is not working with internal DNS Express which is getting it's records of a Windows server
The results look fine from a dig but no web access - Not FW as the browser responds with resolution error
$ dig @internal1 tst.wa.au q-opt any
; <<>> DiG 9.11.4-P2-RedHat-9.11.4-9.P2.el7 <<>> @internal1 tst.wa.au q-opt any
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 57169
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
tst.wa.au IN A
;; ANSWER SECTION:
tst.wa.au 3600 IN CNAME aut.azurewebsites.net.
;; Query time: 4 msec
;; SERVER: 172.30.96.220#53(172.30.96.220)
;; WHEN: Sat Mar 07 16:04:30 AWST 2020
;; MSG SIZE rcvd: 117
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 22006
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;q-opt. IN ANY
;; AUTHORITY SECTION:
. 15 IN SOA a.root-servers.net. nsld.veign-grs.com. 2020030700 1800 900 604800 86400
Recent Discussions
Related Content
* Getting Started on DevCentral
* Community Guidelines
* Community Terms of Use / EULA
* Community Ranking Explained
* Community Resources
* Contact the DevCentral Team
* Update MFA on account.f5.com
