Alexander Haas
Posted on May 3, 2022
What is DDNS used for?
Dynamic DNS (DDNS) services allow you to reach networks that aren't supplied with a static IP by their ISP.
To reliably communicate with for example your home network, the DDNS-provider usually supplies you with a (sub)domain running an ordinary DNS-server and an update-webservice. A client in the internet can then reach a home network simply by connecting to the supplied DDNS-url. To update the DNS-server the update-webservice url is placed in your router or is manually run from a device inside the home network.
See Dynamic DNS for a more in depth explanation.
Purpose of this tutorial
There are many DDNS tutorials out there. But I found it really difficult to find one thats simple, coherent and up-to-date. I would like to summarize my findings in this tutorial.
I will be using code snippets inspired by other tutorials but I will try to credit all the authors. If I make a mistake at giving credit feel free to contact me.
How to implement your own DDNS configuration
Disclaimer: I'm not an IT-security expert. If you find any vulnerabilities in this configuration please contact me!
DDNS services often cost as much as a separate linux virtual machine server. So if you already have one why not set it up by yourself.
This tutorial is only for linux machines. In particular I did this on a debian 11 VM.
I will be using bind9 as it's one of the most popular DNS Servers. Install it using your favourite package manager like apt:
# apt install bind9
If you intend to use go for the update server install it using the official instructions.
DNS and firewall configuration
Go to your Domain/DNS-provider and edit the DNS-server settings as follows:
home.ddns.example.com 3600 IN NS ns.example.com
home.ddns.example.com will be the url under which you will be able to make a connection to you home network.
I'm using the subdomain ddns
because your configuration will be more readable if intend to add multiple home networks.
ns.example.com 3600 IN A <Your Server IP>
This is the nameserver under which your DNS server runs. This will serve the A-entry (IP) for your home network.
Enter the static server IP of your VM.
update-ddns.example.com 3600 IN A <Your Server IP>
This entry will be the webservice that allows you to update the DNS entry for your home network.
Make sure to allow access to port 53-udp for DNS and port 80/443-tcp (http/https) for updating the "A"-entry in your DNS server in your firewall.
Bind9 configuration
The following is a relatively ordinary DNS configuration appart of a few exceptions.
At this point others often use the utility dnssec-keygen
to generate a symmetric key. In my version of this tool the hmac algorithms weren't included. So I used the tool tsig-keygen.
To generate a symmetric key use:
# tsig-keygen ddnskey >> /secrets/ddnskey
key "ddnskey" {
algorithm hmac-sha256;
secret "BASE64=";
};
ddnskey is the name of the key and can be chosen as you like. This key (the value next to secret
) is the one you pass to a DNS update-tool so it can update the DNS entries.
More about this later.
Make sure to edit the permissions to that file so that the user which later runs the webservice has read access to it.
Next edit /etc/bind/named.conf
to configure bind9. This file may be at a different location if you use something else than debian.
Add the following contents to the file:
key "ddnskey" {
algorithm hmac-sha256;
secret "BASE64=";
};
zone home.ddns.example.com. {
type master;
file "/var/lib/bind/db.home.example.com";
allow-update { key ddnskey; };
};
The first entry is the key output we just generated. The second entry is the definition of a new DNS zone. The zone still has to be defined in the file specified next to file
. I had permission issues when creating the file in the /etc/bind
folder as bind is executed with it's own user. zone-files usually have to go into the folder specified above.
Let's create that file:
$ORIGIN .
$TTL 200 ; 3 minutes 20 seconds
home.ddns.example.com IN SOA ns.example.com. alex.example.com. (
6 ; serial
500 ; refresh (8 minutes 20 seconds)
500 ; retry (8 minutes 20 seconds)
86400 ; expire (1 day)
500 ; minimum (8 minutes 20 seconds)
)
NS ns.example.com.
A 1.2.3.4
I used the zone file here as a base template. Zone files aren't the main subject of this tutorial but they basically represent the actual DNS-Server configuration for that specific zone. This information can be accessed by querying the server. They have strict formatting rules. I found a web tool that makes it easier to work with them.
The important parts are that the TTL should be relatively short because the IP might be very short lived. In the A entry just enter anything as this will be overwritten by our update-script and will hopefully always represent the IP of the home network.
Replace alex.example.com.
with your email.
Reload the bind9 service with:
# systemctl restart bind9
and test with
nsupdate -k /secrets/ddnskey
> server ns.example.com
> update delete home.ddns.example.com A
> update add home.ddns.example.com 200 A 1.2.3.4
> send
This does the following:
- Connect to specified nameserver
- Delete the previous A-entry for your home network Ip
- Set a new A-entry
- Submit
If you have the dnsutils
package installed you can check if the A entry was updated with
dig +trace home.ddns.example.com @8.8.8.8
I found a script in another tutorial that I slightly modified but I unfortunately didn't find the authors again. Please let me know if you know the author and I will credit them.
The following is the aforementioned script:
KEYFILE=/secrets/ddnskey
NAMESERVER="ns.example.com"
ZONE="home.ddns.example.com"
TTL="200"
if [ -z "$1" ]
then
IPADDR="`curl -s ifconfig.me`"
else
IPADDR="$1"
fi
(
echo "server $NAMESERVER"
echo "update delete $ZONE A"
echo "update add $ZONE $TTL A $IPADDR"
echo "send"
) | nsupdate -k /secrets/ddnskey
# EOF
If you want to update your server per http(s): I've written a go server for this purpose.
Posted on May 3, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.