<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Alexander Haas</title>
    <description>The latest articles on DEV Community by Alexander Haas (@haasal).</description>
    <link>https://dev.to/haasal</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F857001%2Fbaeadb63-66ba-4e34-9302-01cb37c41925.png</url>
      <title>DEV Community: Alexander Haas</title>
      <link>https://dev.to/haasal</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/haasal"/>
    <language>en</language>
    <item>
      <title>Set up your own DDNS Server with bind9 and go</title>
      <dc:creator>Alexander Haas</dc:creator>
      <pubDate>Tue, 03 May 2022 14:42:03 +0000</pubDate>
      <link>https://dev.to/haasal/set-up-your-own-ddns-server-with-bind9-and-go-193o</link>
      <guid>https://dev.to/haasal/set-up-your-own-ddns-server-with-bind9-and-go-193o</guid>
      <description>&lt;h2&gt;
  
  
  What is DDNS used for?
&lt;/h2&gt;

&lt;p&gt;Dynamic DNS (DDNS) services allow you to reach networks that aren't supplied with a static IP by their ISP.&lt;br&gt;
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.&lt;/p&gt;

&lt;p&gt;See &lt;a href="https://en.wikipedia.org/wiki/Dynamic_DNS"&gt;Dynamic DNS&lt;/a&gt; for a more in depth explanation.&lt;/p&gt;
&lt;h2&gt;
  
  
  Purpose of this tutorial
&lt;/h2&gt;

&lt;p&gt;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.&lt;br&gt;
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.&lt;/p&gt;
&lt;h2&gt;
  
  
  How to implement your own DDNS configuration
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Disclaimer: I'm not an IT-security expert. If you find any vulnerabilities in this configuration please contact me!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;This tutorial is only for linux machines. In particular I did this on a &lt;em&gt;debian 11&lt;/em&gt; VM.&lt;/p&gt;

&lt;p&gt;I will be using &lt;em&gt;bind9&lt;/em&gt; as it's one of the most popular DNS Servers. Install it using your favourite package manager like apt:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;# apt install bind9&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If you intend to use go for the update server install it using the &lt;a href="https://go.dev/doc/install"&gt;official instructions&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  DNS and firewall configuration
&lt;/h3&gt;

&lt;p&gt;Go to your Domain/DNS-provider and edit the DNS-server settings as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;home.ddns.example.com 3600 IN NS ns.example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;home.ddns.example.com will be the url under which you will be able to make a connection to you home network.&lt;br&gt;
I'm using the subdomain &lt;code&gt;ddns&lt;/code&gt; because your configuration will be more readable if intend to add multiple home networks.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ns.example.com 3600 IN A &amp;lt;Your Server IP&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the nameserver under which &lt;em&gt;your&lt;/em&gt; DNS server runs. This will serve the &lt;em&gt;A&lt;/em&gt;-entry (IP) for your home network.&lt;br&gt;
Enter the &lt;strong&gt;static&lt;/strong&gt; server IP of your VM.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;update-ddns.example.com 3600 IN A &amp;lt;Your Server IP&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This entry will be the webservice that allows you to update the DNS entry for your home network. &lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bind9 configuration
&lt;/h3&gt;

&lt;p&gt;The following is a relatively ordinary DNS configuration appart of a few exceptions.&lt;/p&gt;

&lt;p&gt;At this point others often use the utility &lt;code&gt;dnssec-keygen&lt;/code&gt; to generate a symmetric key. In my version of this tool the &lt;em&gt;hmac&lt;/em&gt; algorithms weren't included. So I used the tool &lt;em&gt;tsig-keygen&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;To generate a symmetric key use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# tsig-keygen ddnskey &amp;gt;&amp;gt; /secrets/ddnskey
key "ddnskey" {
    algorithm hmac-sha256;
    secret "BASE64=";
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;ddnskey&lt;/em&gt; is the name of the key and can be chosen as you like. This key (the value next to &lt;code&gt;secret&lt;/code&gt;) is the one you pass to a DNS update-tool so it can update the DNS entries.&lt;br&gt;
More about this later.&lt;br&gt;
Make sure to edit the permissions to that file so that the user which later runs the webservice has &lt;em&gt;read&lt;/em&gt; access to it.&lt;/p&gt;

&lt;p&gt;Next edit &lt;code&gt;/etc/bind/named.conf&lt;/code&gt; to configure bind9. This file may be at a different location if you use something else than debian.&lt;/p&gt;

&lt;p&gt;Add the following contents to the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;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; };
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;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 &lt;code&gt;file&lt;/code&gt;. I had permission issues when creating the file in the &lt;code&gt;/etc/bind&lt;/code&gt; folder as bind is executed with it's own user. zone-files usually have to go into the folder specified above.&lt;/p&gt;

&lt;p&gt;Let's create that file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$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
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I used the zone file &lt;a href="https://linux.robert-scheck.de/netzwerk/eigener-dyndns-dienst/"&gt;here&lt;/a&gt; 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 &lt;a href="http://zonefile.org/"&gt;web tool&lt;/a&gt; that makes it easier to work with them.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;Replace &lt;code&gt;alex.example.com.&lt;/code&gt; with your email.&lt;/p&gt;

&lt;p&gt;Reload the bind9 service with:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;# systemctl restart bind9&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;and test with&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nsupdate -k /secrets/ddnskey 
&amp;gt; server ns.example.com
&amp;gt; update delete home.ddns.example.com A
&amp;gt; update add home.ddns.example.com 200 A 1.2.3.4
&amp;gt; send
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This does the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Connect to specified nameserver&lt;/li&gt;
&lt;li&gt;Delete the previous A-entry for your home network Ip&lt;/li&gt;
&lt;li&gt;Set a new A-entry&lt;/li&gt;
&lt;li&gt;Submit&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you have the &lt;code&gt;dnsutils&lt;/code&gt; package installed you can check if the A entry was updated with&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dig +trace home.ddns.example.com @8.8.8.8
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;The following is the aforementioned script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;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
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want to update your server per http(s): I've written a &lt;a href="https://github.com/haasal/ddns-update-server"&gt;go server&lt;/a&gt; for this purpose.&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>linux</category>
      <category>dns</category>
      <category>go</category>
    </item>
  </channel>
</rss>
