Until November 2020 I had a fixed IP address which meant that connecting to my server from the outside world was easy, I updated my domain registrar DNS information with the IP address allocated to me by my ISP and away I went. However, I changed to FTTP (Fibre to the premises) in November 2020 and lost my fixed IP address ( I got a great offer for 300MB download and 50MB upload speeds which was about £15 a month cheaper than an ISP that would provide a fixed IP on the same sort of speeds).
Obviously, this now meant that I couldn’t be sure what my external IP address would be, my router does support Dynamic DNS but has a rather limited selection of service providers (and also only seems to cater for a single hostname for the generic setting) so I needed to find another solution.
I had a quick look round and one of the first dynamic DNS providers, that allows you to use your own domain instead of one of their subdomains, I found was ydns so I registered for an account, configured a couple of domains and changed the nameserver settings at my domain registrar to the ydns servers.
So far, so good, but what happens if I reboot the router and it obtains a different IP address? Obviously, the DNS settings will now be incorrect. Fortunately ydns provide a few options for updating the information, I’m using the basic updater script that ydns provide. My hostnames are in the script and I have a cronjob running on the proxy server that runs every few minutes and if my internet facing IP address changes it updates the ydns API with the new IP addresses.
This is not a perfect solution as if my IP address changes it takes a while for the new IP address to propagate around other DNS servers which means that for a short time I will not be able to access my home server, however, as the IP address rarely changes (my router is pretty stable) I’m happy to take this risk. I’ve also configured the TTL to be 1800 seconds (30 minutes) so any updates should be propagated to other DNS servers around the world within 30 minutes of the update, this means that within 30 minutes of my IP address being updated I can access my server again. As I’m not running anything mission critical on there I can live with this.
YDNS Updater Script
The script below is how used to update the ip address with ydns, multiple hostnames are separated by a space so remember to update the script if you add another host to your configuration. Just set this script to run every few minutes; it checks the internet facing IP address of your router, and if it’s changed since the last check sends the updated address to the ydns servers.
##
# Define your YDNS account details and host you'd like to update.
# In case you'd like to update multiple hosts at once, provide the hosts
# separated by space.
##
YDNS_USER="username_goes_here"
YDNS_PASSWD="ydns_api_key_goes_here"
YDNS_HOST="www.example.com media.example.com host3.example.com host4.example.com"
YDNS_LASTIP_FILE="/tmp/ydns_last_ip_$YDNS_HOST"
##
# Don't change anything below.
##
YDNS_UPD_VERSION="20170905.1"
if ! hash curl 2>/dev/null; then
echo "ERROR: cURL is missing."
exit 1
fi
usage () {
echo "YDNS Updater"
echo ""
echo "Usage: $0 [options]"
echo ""
echo "Available options are:"
echo " -h Display usage"
echo " -H HOST YDNS host to update"
echo " -u USERNAME YDNS username for authentication"
echo " -p PASSWORD YDNS password for authentication"
echo " -i INTERFACE Use the local IP address for the given interface"
echo " -v Display version"
echo " -V Enable verbose output"
exit 0
}
## Shorthand function to update the IP address
update_ip_address () {
# if this fails with error 60 your certificate store does not contain the certificate,
# either add it or use -k (disable certificate check
ret=
for host in $YDNS_HOST; do
ret=`curl --basic \
-u "$YDNS_USER:$YDNS_PASSWD" \
--silent \
https://ydns.io/api/v1/update/?host=${host}\&ip=${current_ip}`
done
echo ${ret//[[:space:]]/}
}
## Shorthand function to display version
show_version () {
echo "YDNS Updater version $YDNS_UPD_VERSION"
exit 0
}
## Shorthand function to write a message
write_msg () {
if [ $verbose -ne 1 ]; then
return
fi
outfile=1
if [ -n "$2" ]; then
outfile=$2