<p>
The domain name system (DNS) resolves hostnames (e.g. <code>www.example.net</code>) to IP addresses.<br />
BIND is the most used DNS server on the internet.
</p>
<p>
This tutorial shows how to configure a subdomain in BIND 9 on Debian 10 (buster).
</p>

<h3>Contents</h3>
<ul>
<li><a href="#install">Installation</a></li>
<li><a href="#domain">Domain</a></li>
<li><a href="#firewall">Firewall</a></li>
<li><a href="#config">Configuration</a>
<ul>
<li><a href="#config_zone">Zone</a></li>
<li><a href="#config_reload">Reload</a></li>
</ul>
</li>
<li><a href="#test">Test</a></li>
<li><a href="#dynamic">Dynamic Updates</a>
<ul>
<li><a href="#dynamic_config">Configuration</a></li>
<li><a href="#dynamic_client">Client</a></li>
</ul>
</li>
<li><a href="#links">External Links for further Information</a></li>
</ul>

<h3 id="install">Installation</h3>
<p>
The official Debian repository includes BIND 9:
</p>
<pre><code class="language-bash">apt install bind9</code></pre>

<h3 id="domain">Domain</h3>
<p>
To run a name server for a subdomain <code>sub.example.net</code>,<br />
the following records are relevant in the zone of the domain <code>example.net</code>:
</p>
<pre class="file"><code class="language-dns">sub      IN  NS    ns1.sub.example.net.  ; name server for subdomain sub.example.net
ns1.sub  IN  A     192.0.2.1             ; IPv4 address of ns1.sub.example.net
ns1.sub  IN  AAAA  2001:db8:10::1        ; IPv6 address of ns1.sub.example.net
</code></pre>

<h3 id="firewall">Firewall</h3>
<p>
The DNS server <code>ns1.sub.example.net</code> needs to accept incoming packages<br />
on the following ports:
</p>
<ul>
<li>TCP port 53</li>
<li>UDP port 53</li>
</ul>

<h3 id="config">Configuration</h3>
<p>
The zone file for <code>sub.example.net</code> needs to be specified in the configuration file:
</p>
<dl class="file">
<dt><code class="filename">/etc/bind/named.conf.local</code></dt>
<dd>
<pre class="file"><code class="language-plaintext">zone "sub.example.net" {
    type master;
    file "/var/lib/bind/db.sub.example.net";
};
</code></pre>
</dd>
</dl>

<h4 id="config_zone">Zone</h4>
<p>
The zone file defines records for a (sub)domain.<br />
Here is an exemplary zone file for the subdomain <code>sub.example.net</code>:
</p>
<dl class="file">
<dt><code class="filename">/var/lib/bind/db.sub.example.net</code></dt>
<dd>
<pre class="file"><code class="language-dns">$TTL  86400
@         IN  SOA   ns1.sub.example.net. root.example.net. (
                    2020042301    ; Serial  (YYYYMMDDxx)
                          3600    ; Refresh  (1 hour)
                           600    ; Retry  (10 mins)
                        604800    ; Expire  (7 days)
                          1800 )  ; Negative Cache TTL  (30 mins)

@         IN  NS    ns1.sub.example.net.
ns1       IN  A     192.0.2.1
ns1       IN  AAAA  2001:db8:10::1

; other hostnames
somehost  IN  A     192.0.2.10
another   IN  A     192.0.2.11
</code></pre>
</dd>
</dl>
<p>
The content of the exemplary zone file means the following:
</p>
<ul>
<li>The default time to live (TTL) for each record is set to 86400 seconds (1 day).</li>
<li>"<code>@</code>" is an alias for the zone itself (<code>sub.example.net</code>).</li>
<li>The start of authority (SOA) record contains administrative information<br />
about the zone: name server, mail address, serial number, ...</li>
<li>The name server <code>ns1.sub.example.net</code> for the subdomain <code>sub.example.net</code> is<br />
specified in the NS record.</li>
<li>IPv4 addresses are stored in A records.</li>
<li>AAAA records contain IPv6 addresses.</li>
</ul>

<h4 id="config_reload">Reload</h4>
<p>
The following command reloads the configuration:
</p>
<pre><code class="language-bash">rndc reload</code></pre>

<h3 id="test">Test</h3>
<p>
Install the <code>dnsutils</code> package:
</p>
<pre><code class="language-bash">apt install dnsutils</code></pre>
<p>
Verify that the DNS lookup returns the correct IP address:
</p>
<pre><code class="language-bash">nslookup somehost.sub.example.net</code></pre>

<h3 id="dynamic">Dynamic Updates</h3>
<p>
Updating the DNS records is useful when IP addresses are dynamically assigned.<br />
For instance, DHCP servers automatically assign IP addresses to hosts.
</p>

<h4 id="dynamic_config">Configuration</h4>
<p>
The following command generates a random rndc key and<br />
prints a configuration example to the terminal:
</p>
<pre><code class="language-bash">rndc-confgen</code></pre>
<p>
To allow a client to update the DNS records of <code>sub.example.net</code> with an rndc key,<br />
enable it in the configuration file:
</p>
<dl class="file">
<dt><code class="filename">/etc/bind/named.conf.local</code></dt>
<dd>
<pre class="file"><code class="language-dns">include "/etc/bind/rndc.key";

zone "sub.example.net" {
    type master;
    file "/var/lib/bind/db.sub.example.net";
    allow-update { key "rndc-key"; };
};
</code></pre>
</dd>
</dl>

<h4 id="dynamic_client">Client</h4>
<p>
For updating DNS records, the following command line tool is used:
</p>
<pre><code class="language-bash">nsupdate</code></pre>
<p>
These commands update the IPv4 address of <code>somehost.sub.example.net</code>:
</p>
<pre><code class="language-plaintext">key rndc-key C3...DQ==
update delete somehost.sub.example.net A
update add somehost.sub.example.net 86400 A 192.0.2.123
send
</code></pre>

<h3 id="links">External Links for further Information</h3>
<ul>
<li><a href="https://www.isc.org/bind/" target="_blank">
https://www.isc.org/bind/</a></li>
<li><a href="https://tools.ietf.org/html/rfc1035" target="_blank">
https://tools.ietf.org/html/rfc1035</a></li>
<li><a href="https://en.wikipedia.org/wiki/Zone_file" target="_blank">
https://en.wikipedia.org/wiki/Zone_file</a></li>
<li><a href="https://wiki.debian.org/Bind9" target="_blank">
https://wiki.debian.org/Bind9</a></li>
</ul>