Dynamic DNS, also known as DDNS

DDNS service lets you access your home computer (Router) for example ftp from anywhere in the world.

You do not need more such DynDNS providers, you can easily build a DynDNS server yourself.
This tutorial will  show the required steps to setup DynDNS on your Ubuntu or Debian machine with a static IP Address.

You should have the following:

  • A Linux server with root access
  • Access to the DNS server hosting your domain and the ability to customize the zone file yourself.

First of all create a subdomain for DNS-Server


dyndns   IN A       [IP-ADRESSE]
dyndns   IN NS      dyndns.myDomainName.

To make it easier to copy/paste commands, we define a few variables


Generating a key-pair

dnssec-keygen -a hmac-sha256 -b 256 -n HOST $ZONE.
dyndns.euve8639.vserver.de. IN KEY 512 3 163 7S2K2LCtBZfXmucM80cmXghXxwUz1IBM7AyhWcPDJzE=

It creates two files.

One will be the server copy of the key file, and can contain multiple keys,
the other will be a single file named after the host that we’re going to be updating,
and needs to be moved to the host itself, for later use.
Now move the file $ZONE.key to the host which is going to be doing the updating and change the permissions on it.

-:~$ sudo chown root:bind /etc/bind/$ZONE.keys
-:~$ sudo chmod u=rw,g=r,o= /etc/bind/$ZONE.keys

Installing and configuring bind9

-:~$ sudo apt-get install bind9-host bind9utils dnsutils

Update the configuration file for bind “/etc/bind/named.conf.options“ and we should set the followings parameters:

– Allow Query to your dns from your private network (As the name suggests only the systems from your private network can query dns sever for name to ip translation and vice-versa)
– Allow recursive query
– Specify the DNS port ( 53)
– Forwarders (DNS query will be forwarded to the forwarders when your local DNS server is unable to resolve query)

-:~$ sudo vi /etc/bind/named.conf.options

options {
        directory "/var/cache/bind";
        forwarders {; };
        recursion yes;
        auth-nxdomain no; # conform to RFC1035
        listen-on port 53 { localhost;; };
        allow-query { localhost;; };
        // If BIND logs error messages about the root key being expired,
        // you will need to update your keys.  See https://www.isc.org/bind-keys
        dnssec-validation auto;
        auth-nxdomain no;    # conform to RFC1035
        //listen-on-v6 { any; };

Allow firewall 53 port for bind server

-:~$ sudo ufw allow 53

Update the configuration file ‘/etc/bind/named.conf.local’ to define the zone files for our zone as followed:

-:~$ sudo vi /etc/bind/named.conf.local

// DDNS keys
zone    "$DOMIN"   {
        type master;
        file    "/etc/bind/forward.$DOMIN";

zone   "0.168.192.in-addr.arpa"        {
       type master;
       file    "/etc/bind/reverse.$DOMIN";

--sed -i -e "s/\$DOMIN/$DOMIN/g" /etc/bind/named.conf.local

Validating Syntax of bind9 configuration and Zone files

-:~$ sudo named-checkconf /etc/bind/named.conf.local

Now create the forward lookup zone file. You can use the zone files (/etc/bind/db.local) and generate a copy of the file.

-:~$ sudo cp /etc/bind/db.local /etc/bind/forward.$DOMIN

-:~$ sudo vi /etc/bind/forward.$DOMIN

$TTL    604800

@       IN      SOA     $ZONE. root.$ZONE. (
                              6         ; Serial
                         604820         ; Refresh
                          86600         ; Retry
                        2419600         ; Expire
                         604600 )       ; Negative Cache TTL

;Name Server Information
@       IN      NS      $ZONE.

;IP address of Your Domain Name Server(DNS)
dyndns  IN       A

;Mail Server MX (Mail exchanger) Record
forgani.de. IN  MX  10  mail.$DOMIN.

;A Record for Host names
www     IN       A
mail    IN       A

;CNAME Record
ftp     IN      CNAME    www.$DOMIN.

Next we create a reverse lookup zone file at the same location,sample reverse lookup zone file is present at ‘/etc/bind‘ folder.

-:~$ sudo cp /etc/bind/db.127 reverse.$DOMIN
-:~$ sudo vi /etc/bind/reverse.$DOMIN

$TTL    604800
@       IN      SOA     $DOMIN. root.$DOMIN. (
                             21         ; Serial
                         604820         ; Refresh
                          864500        ; Retry
                        2419270         ; Expire
                         604880 )       ; Negative Cache TTL

;Your Name Server Info
@       IN      NS      dyndns.$DOMIN.
dyndns  IN      A

;Reverse Lookup for Your DNS Server
40      IN      PTR     dyndns.$DOMIN.

;PTR Record IP address to HostName
50      IN      PTR     www.$DOMIN.
60      IN      PTR     mail.$DOMIN.

Restart the BIND service for the changes

-:~$ sudo systemctl restart bind9
-:~$ sudo systemctl enable bind9

To cross verify the syntax your forward and reverse lookup zone files , use the command “named-checkzone“, example is shown below:

-:~$ sudo named-checkzone  /etc/bind/named.conf.local /etc/bind/forward.$DOMIN

Testing the DNS server with dig and nslookup

Use the dig command to find out DNS & its related information and verify the output shows that DNS is working
(dig is a part of dnsutils debian package)

:~$ dig $ZONE

check the reverse lookup query(PTR):

:~$ dig -x $IP-ADDRESS

Run ‘nslookup’ command against the DNS server to confirm the output of dig command

-:~$ nslookup $ZONE


cat <<EOF | nsupdate -k /etc/bind/key.$CLIENT
server $HOST
zone $ZONE.
update delete $CLIENT.
update add $CLIENT. 60 A
update add $CLIENT. 60 TXT "Updated on $(date)"

Creating the empty Zone
The content of the zone file, depending on what exactly you’re trying to achieve.
This is created in /var/lib/bind/$ZONE

  echo '$ORIGIN .'
  echo '$TTL 300 ; 5 minutes'
  echo '$ZONE IN SOA $HOST. root@$DOMIN. ('
  echo '  1 ; serial (start at 1 for a dynamic zone instead of the usual date-based serial)'
  echo '  3600 ; refresh by secondaries (but they get NOTIFY-ed anyway)'
  echo '  600 ; retry (every 10 minutes if refresh fails)'
  echo '  604800 ; expire (slaves remove the record after 1 week if they could not refresh it)'
  echo '  300 ; minimum ttl for negative answers (5 minutes)'
  echo ')'
  echo 'NS $HOST.'
  echo '$ORIGIN $ZONE.'
} > /var/lib/bind/$ZONE

sed -i -e "s/\$HOST/$HOST/" -e "s/\$ZONE/$ZONE/g" -e "s/\$DOMIN/$DOMIN/g" /var/lib/bind/$ZONE service bind9 restart


cat <<EOF | nsupdate -k /etc/bind/key.$CLIENT
server $HOST
zone $ZONE.
update delete $CLIENT.
update add $CLIENT. 60 A
update add $CLIENT. 60 TXT "Updated on $(date)"

Check the result:

#host -t ANY $HOST.$ZONE
host -t $CLIENT $HOST

Leave a Reply

Your email address will not be published. Required fields are marked *