Dynamic DNS bash shell script for IPv6 prefix using token or DHCPv6 for Linux

A bash script to update your preferred Dynamic DNS service with dynamic IPv6 prefix. There are two versions of this script, one with IPv6 token and one with DHCPv6. If you use your router to set a fixed suffix then you can use the DHCPv6 version or if you use IPv6 token to set a suffix then use the token version.

First step is to create a text file which will contain the IPv6 address to compare with the new one. Run these commands to automatically create the file with a 0 in it.

Bash command
echo "0" > $HOME/ddns-ipv6-address.txt
chmod 777 $HOME/ddns-ipv6-address.txt

If you choose to manually create the file then first create a blank file storedipaddress.txt and save it in /root/ddns-ipv6-address.txt, now open the file and type 0 and save and close the file. For some reason the storedipaddress.txt should not be empty for comparison this is why I had to type zero and save the file. Give the permissions 0777 to storedipaddress.txt so the script can write to it.

If you use token to set your IPv6 suffix:

Second step:

Now create a new file ddns-updater-hourly and save it in /etc/cron.hourly/ddns-updater-hourly (file name should not have any extension) and chmod 0755 for permission.

Example suffix used in this script 71c6:b34f:8e2a:54f5

Change the section "# Your DDNS update command goes here" with the command you are given by your DDNS provider such as Cloudflare.

/etc/cron.hourly/ddns-updater-hourly file content

/etc/cron.hourly/ddns-updater-hourly
#!/bin/bash

SUFFIX="::71c6:b34f:8e2a:54f5"
ADDRSTORE=$HOME/ddns-ipv6-address.txt
STOREDIPV6=$(cat $ADDRSTORE)

__rfc5952_expand () {
    read addr mask < <(IFS=/; echo $1)
    quads=$(grep -oE "[a-fA-F0-9]{1,4}" <<< ${addr/\/*} | wc -l)
    grep -qs ":$" <<< $addr && { addr="${addr}0000"; (( quads++ )); }
    grep -qs "^:" <<< $addr && { addr="0000${addr}"; (( quads++ )); }
    [ $quads -lt 8 ] && addr=${addr/::/:$(for (( i=1; i<=$(( 8 - quads )) ; i++ )); do printf "0000:"; done)}
    addr=$(for quad in $(IFS=:; echo ${addr}); do printf "${delim}%04x" "0x${quad}"; delim=":"; done)
    [ ! -z $mask ] && echo $addr/$mask || echo $addr
}

SUFFIX="$(__rfc5952_expand $SUFFIX)"
SUFFIX=${SUFFIX: -19}
ALLIPV6=$(/sbin/ip -6 addr | grep inet6 | awk -F '[ \t]+|/' '{print $3}' | grep '^2')
for i in $ALLIPV6; do
EXPANDED="$(__rfc5952_expand $i)"
EXPANDEDSUFFIX=${EXPANDED: -19}
if [ $EXPANDEDSUFFIX == $SUFFIX ]; then

if [ $EXPANDED != $STOREDIPV6 ]; then
# Your DDNS update command(s) go here
# Use the variable $EXPANDED to substitute the IPv6 address in your script.
echo $EXPANDED > $ADDRSTORE
logger "DDNS new IP address detected $EXPANDED"
fi

fi
done
exit 0

If you use DHCPv6 to set your IPv6 suffix:

If you use your router to set a static suffix using DHCPv6 then use this script since there is no need to use a token.

First step:

It is the same as above to create a text file to store the IPv6 address. Follow the command above or manually create a text file in the correct location.

Second step:

/etc/cron.hourly/ddns-updater-hourly file content

/etc/cron.hourly/ddns-updater-hourly
#!/bin/bash

SUFFIX="::71c6:b34f:8e2a:54f5"
ADDRSTORE=$HOME/ddns-ipv6-address.txt
STOREDIPV6=$(cat $ADDRSTORE)

__rfc5952_expand () {
    read addr mask < <(IFS=/; echo $1)
    quads=$(grep -oE "[a-fA-F0-9]{1,4}" <<< ${addr/\/*} | wc -l)
    grep -qs ":$" <<< $addr && { addr="${addr}0000"; (( quads++ )); }
    grep -qs "^:" <<< $addr && { addr="0000${addr}"; (( quads++ )); }
    [ $quads -lt 8 ] && addr=${addr/::/:$(for (( i=1; i<=$(( 8 - quads )) ; i++ )); do printf "0000:"; done)}
    addr=$(for quad in $(IFS=:; echo ${addr}); do printf "${delim}%04x" "0x${quad}"; delim=":"; done)
    [ ! -z $mask ] && echo $addr/$mask || echo $addr
}

SUFFIX="$(__rfc5952_expand $SUFFIX)"
SUFFIX=${SUFFIX: -19}
ALLIPV6=$(/sbin/ip -6 addr | grep inet6 | awk -F '[ \t]+|/' '{print $3}' | grep '^2')
for i in $ALLIPV6; do
EXPANDED="$(__rfc5952_expand $i)"
EXPANDEDSUFFIX=${EXPANDED: -19}
if [ $EXPANDEDSUFFIX == $SUFFIX ]; then

if [ $EXPANDED != $STOREDIPV6 ]; then
# Your DDNS update command(s) go here
# Use the variable $EXPANDED to substitute the IPv6 address in your script.
echo $EXPANDED > $ADDRSTORE
logger "DDNS new IP address detected $EXPANDED"
fi

fi
done
exit 0

Now edit the variables with your own values and save the file and it should run every hour to update the DDNS server.  You can also save the file somewhere else and create your own cron job to your desired schedule.

Let me know if you have any comments or if there is any bug or error in this guide.

Related: Server setup for dynamic IPv6 prefix

❮ Back to blog