[BALUG-Talk] DNS ... CNAME records ... to CNAMES? How long a chain? Loops? ...

Michael Paoli Michael.Paoli@cal.berkeley.edu
Sun Oct 9 20:58:56 UTC 2022


DNS ... CNAME records ... to CNAMES?  How long a chain?  Loops? ...

So, sometimes the question comes up, can you do a CNAME to a CNAME?
Yes, ... but not recommended.  What about CNAME to CNAME to CNAME ...?
Again, not recommended, but within reason, it will still work.
Up to?  Probably 8, ... maybe 16 ... more than that?  Hypothetically,
but mostly not.
What about a CNAME loop?  That should cleanly fail ... but that
doesn't mean it always does.

I set up some CNAME "test" records again ... if folks wanted to poke at
such a bit and see how it behaves.
First teensy primer on number bases >10 and >16 ... just continue the
character sequence so ... I use some base36 - characters go from 0
through 9 then a through z.  I did that to make the
coding/interpretation of such fairly easy to be able to go up to 36 with
a single character.
Anyway, set up temporarily (goes away
# at -l | fgrep root
71      Sat Nov 12 09:52:00 2022 a root
)
fair number of CNAME records one can poke at, notably a chain, and
several loops.
So, the chain ... eventually resolves to working IPs ..., we have:
cc-0-tmp.balug.org. IN CNAME www.balug.org.
cc-1-tmp.balug.org. IN CNAME cc-0-tmp.balug.org.
cc-2-tmp.balug.org. IN CNAME cc-1-tmp.balug.org.
cc-3-tmp.balug.org. IN CNAME cc-2-tmp.balug.org.
...
cc-h-tmp.balug.org. IN CNAME cc-g-tmp.balug.org.
cc-i-tmp.balug.org. IN CNAME cc-h-tmp.balug.org.
cc-j-tmp.balug.org. IN CNAME cc-i-tmp.balug.org.
(cc - think Cname Chain) so, a chain of 20 (0 through j, base36) CNAME
records.
Feel free to, e.g. try resolving, doing some use of dig(1) to lookup the
DNS data, etc.
Oh, and yes, works as a web site ... cert even matches those names ...
but since those CNAMES aren't canonical names for that site, the website
is configured to redirect to a canonical name for the web site.
Loops!  Yes, also set up CNAME loops of various sizes one can poke at:
cl-0-tmp.balug.org. IN CNAME cl-0-tmp.balug.org.
cl-01-tmp.balug.org. IN CNAME cl-10-tmp.balug.org.
cl-10-tmp.balug.org. IN CNAME cl-01-tmp.balug.org.
cl-012-tmp.balug.org. IN CNAME cl-201-tmp.balug.org.
cl-120-tmp.balug.org. IN CNAME cl-012-tmp.balug.org.
cl-201-tmp.balug.org. IN CNAME cl-120-tmp.balug.org.
...
cl-0123456789abcdef-tmp.balug.org. IN CNAME 
cl-f0123456789abcde-tmp.balug.org.
...
cl-0123456789abcdefg-tmp.balug.org. IN CNAME 
cl-g0123456789abcdef-tmp.balug.org.
...
cl-0123456789abcdefgh-tmp.balug.org. IN CNAME 
cl-h0123456789abcdefg-tmp.balug.org.
So cl (think Cname Loop), loops from 1 to 18 CNAME records in each loop.
If we use > to represent our link, we have these loops - showing the
portion that varies in each name:
0>0
01>10>01
012>201>120>012
...
0123456789abcdefgh>h0123456789abcdefg>...>0123456789abcdefgh

Also, RFC 1034 (look for "loop" within) we have:
The recommended
priorities for the resolver designer are:

    1. Bound the amount of work (packets sent, parallel processes
       started) so that a request can't get into an infinite loop or
       start off a chain reaction of requests or queries with other
       implementations EVEN IF SOMEONE HAS INCORRECTLY CONFIGURED
       SOME DATA.

domain software should not fail when presented with CNAME
chains or loops; CNAME chains should be followed and CNAME loops
signaled as an error.

Multiple levels of
aliases should be avoided due to their lack of efficiency, but should
not be signaled as an error.  Alias loops and aliases which point to
non-existent names should be caught and an error condition passed back
to the client.

If a CNAME RR is present at a node, no other data should be
present; this ensures that the data for a canonical name and its aliases
cannot be different.

And ... was pretty easy to write little program
to create the records ... and get rid of same records.
Yes, Dynamic DNS (DDNS) also makes it quite nice 'n easy,
and also at(1) to later do the removals:
#!/bin/sh

# add/del CNAME chain / loop(s)

set -e

suffix=-tmp.balug.org.
ttl=300
b="$(basename "$0")"
case "$b" in
     add|CNAMEadd)
         adddel=add
     ;;
     del|CNAMEdel)
         adddel=del
     ;;
     *)
         echo "$0: expecting to be invoked as add, CNAMEadd, del, or" \
             "CNAMEdel, aborting" 1>&2
         exit 1
     ;;
esac

# our base36 digits:
seq=0123456789abcdefghijklmnopqrstuvwxyz # max 36

{
     # CNAME chain
     prefix=cc- # Cname Chain
     c0=www.balug.org. # Chain 0 to (anchor)
     max=20 # integer between 2 and 36, this is count, not value
     set -- \
         $(
             echo "$seq" |
             sed -ne '
                 s/^\(.\{'"$max"'\}\).*$/\1/
                 s/./& /gp
             '
         )
     o="$1"; shift
     echo "update $adddel $prefix$o$suffix $ttl IN CNAME $c0"
     while :
     do
         case "$1" in ?):;;*)break;;esac # break if < 1 arg
         echo "update $adddel $prefix$1$suffix $ttl IN CNAME" \
             "$prefix$o$suffix"
         o="$1"; shift
     done

     # CNAME loops
     prefix=cl- # Cname Loop
     max=18 # integer between 1 and 36
     n="$max"
     while [ "$n" -ge 1 ]
     do
         a=$(
             echo "$seq" |
             sed -ne 's/^\(.\{'"$n"'\}\).*$/\1/p'
         )
         while :
         do
             b=$(
                 echo "$a" |
                 sed -ne 's/^\(.*\)\(.\)$/\2\1/p'
             )
             echo "update $adddel $prefix$a$suffix $ttl IN CNAME" \
                 "$prefix$b$suffix"
             case "$b" in 0*) break;; esac # last one
             a="$b"
         done
         n="$(expr "$n" - 1)"
     done

     echo send
} |
nsupdate -l



More information about the BALUG-Talk mailing list