Forum Discussion

dstogsdill_2492's avatar
dstogsdill_2492
Icon for Nimbostratus rankNimbostratus
Nov 04, 2012

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

  • 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?
  • 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_104974's avatar
    gbbaus_104974
    Historic F5 Account
    Not 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_104974's avatar
    gbbaus_104974
    Historic F5 Account
    Not 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

     

     

  • 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!
  • 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's avatar
      Mudhen_64776
      Icon for Nimbostratus rankNimbostratus

      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's avatar
        anonomike
        Icon for Nimbostratus rankNimbostratus

        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