<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>DNS &#8211; Blog of Kliment Andreev &#8211; A place so I won&#039;t forget things</title>
	<atom:link href="https://blog.andreev.it/tag/dns/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.andreev.it</link>
	<description></description>
	<lastBuildDate>Thu, 05 Nov 2020 22:05:48 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	
	<item>
		<title>CentOS: Install an authoritative DNS server (BIND)</title>
		<link>https://blog.andreev.it/2018/12/141-centos-install-an-authoritative-dns-server-bind/</link>
					<comments>https://blog.andreev.it/2018/12/141-centos-install-an-authoritative-dns-server-bind/#respond</comments>
		
		<dc:creator><![CDATA[Kliment Andreev]]></dc:creator>
		<pubDate>Wed, 19 Dec 2018 20:50:09 +0000</pubDate>
				<category><![CDATA[CentOS]]></category>
		<category><![CDATA[BIND]]></category>
		<category><![CDATA[centos]]></category>
		<category><![CDATA[DNS]]></category>
		<guid isPermaLink="false">https://blog.andreev.it/?p=4219</guid>

					<description><![CDATA[In this post I&#8217;ll explain how to install and configure BIND DNS server to&#8230;]]></description>
										<content:encoded><![CDATA[<div id="bsf_rt_marker"></div><p>In this post I&#8217;ll explain how to install and configure BIND DNS server to act as an authoritative server for a public domain in a master/slave configuration. This is not a setup for a server that will act as a DNS server in your local environment and does DNS resolution for your local network. In this post, the DNS server won&#8217;t resolve any DNS queries except for the domain that it is authoritative. The domain that I&#8217;ll use is <strong>cloudwerk.us</strong> registered with Go Daddy, so some of the configurations will apply to Go Daddy only. The IPs and keys that I&#8217;ll use will be visible. The setup will be gone by the time you read this.<br />
So, I have my master server, <strong>ns1.cloudwerk.us (67.205.160.87)</strong> and the slave server <strong>ns2.cloudwerk.us (104.248.184.142)</strong>.<br />
I will be using CentOS 7.5 and BIND 9.9.4-72. Before you start, make sure you have your domain purchased and you have 2 servers with public IPs up and running. You can leave the default registrant&#8217;s DNS servers for now. </p>
<h1>Installation, startup and control</h1>
<p>First, I&#8217;ll install BIND on both servers. All commands below are executed as root.</p>
<pre class="brush: bash; title: ; notranslate">
yum -y install bind
</pre>
<p>Then, we have to configure the <strong>rndc (Remote Name Daemon Control) </strong>utility. This utility allows management of the <strong>named </strong>(DNS) daemon. Moreover, you can manage remote DNS servers and I&#8217;ll explain how. So, let&#8217;s create the keys (highlighted line is what you type, the rest is output). DO this on the master server only.</p>
<pre class="brush: bash; highlight: [1]; title: ; notranslate">
rndc-confgen -a -r /dev/urandom 
wrote key file &quot;/etc/rndc.key&quot; 
</pre>
<p>As you can see, there is a file called <strong>rndc.key</strong> created under <strong>/etc</strong> directory. This is the default directory where BIND expects to find its config files. The zone files are under <strong>/var</strong>.<br />
Now, copy this file to the second server in the same location. You can use scp, copy &#038; paste in a terminal session, it doesn&#8217;t matter. What matters is that you have to change the permissions and the owner of the file. BIND runs under the <strong>named </strong>user, not root. Do this on both servers. </p>
<pre class="brush: bash; title: ; notranslate">
cd /etc
chown root:named rndc.key
chmod 640 rndc.key
</pre>
<p>Let&#8217;s make sure that BIND starts on boot. On both servers, execute:</p>
<pre class="brush: bash; title: ; notranslate">
systemctl enable named  
</pre>
<p>Now, we can start the BIND daemon on both. </p>
<pre class="brush: bash; title: ; notranslate">
systemctl start named 
</pre>
<p>Check the logs.</p>
<pre class="brush: bash; highlight: [1]; title: ; notranslate">
tail /var/log/messages
Dec 19 16:33:40 master named&#x5B;1308]: zone 1.0.0.127.in-addr.arpa/IN: loaded serial 0
Dec 19 16:33:40 master named&#x5B;1308]: zone localhost.localdomain/IN: loaded serial 0
Dec 19 16:33:40 master named&#x5B;1308]: zone 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa/IN: loaded serial 0
Dec 19 16:33:40 master named&#x5B;1308]: all zones loaded
Dec 19 16:33:40 master named&#x5B;1308]: running
Dec 19 16:33:40 master systemd: Started Berkeley Internet Name Domain (DNS).
Dec 19 16:33:40 master systemd: Reached target Host and Network Name Lookups.
Dec 19 16:33:40 master systemd: Starting Host and Network Name Lookups.
Dec 19 16:33:40 master named&#x5B;1308]: network unreachable resolving './DNSKEY/IN': 2001:500:84::b#53
Dec 19 16:33:40 master named&#x5B;1308]: network unreachable resolving './NS/IN': 2001:500:84::b#53
</pre>
<p>We can&#8217;t start the server with the <strong>rndc </strong>utility, but we can stop it if needed with <strong>rndc stop</strong> or simply <strong>systemctl stop named</strong>.<br />
To control the slave server from the master, we have to modify the main BIND configuration file, <strong>named.conf</strong> on the slave server. Also, the keys have to be the same, but we already took care of that part above.<br />
So, in the same <strong>/etc</strong> directory, edit <strong>named.conf</strong> and add these lines, right before the <strong>options </strong>directive. Do this on the slave server, not the master.</p>
<pre class="brush: bash; title: ; notranslate">
include &quot;/etc/rndc.key&quot;;

controls {
        inet 127.0.0.1 allow { localhost; } keys { &quot;rndc-key&quot;; };
        inet 104.248.184.142 allow { 67.205.160.87; } keys { &quot;rndc-key&quot;; };
};
</pre>
<p>If you look at my IPs above, this means that the rndc utility will be accepted from the localhost and from the the IP 67.205.160.87 which is the master server. But, we also have to tell BIND to listen on the public IP. By default, it listens on the <strong>localhost </strong>only.<br />
Do this on BOTH servers. In <strong>named.conf</strong> find the <strong>options </strong>directive and modify the <strong>listen-on</strong> option so it looks like this. You should put the public IP of each server there, so the line will differ on both servers. </p>
<pre class="brush: bash; title: ; notranslate">
//Master server
listen-on       { 127.0.0.1; 67.205.160.87; };
</pre>
<pre class="brush: bash; title: ; notranslate">
//Slave server
listen-on       { 127.0.0.1; 104.248.184.142; };
</pre>
<p>Allow traffic on the firewalls if you have them enabled. Do this on both.</p>
<pre class="brush: bash; title: ; notranslate">
firewall-cmd --add-port=53/tcp --permanent 
firewall-cmd --add-port=53/udp --permanent 
</pre>
<p>On the master node, do this.</p>
<pre class="brush: bash; title: ; notranslate">
firewall-cmd --permanent --zone=public --add-rich-rule=' 
  rule family=&quot;ipv4&quot; 
  source address=&quot;104.248.184.142/32&quot; 
  port protocol=&quot;tcp&quot; port=&quot;953&quot; accept'
</pre>
<p>On the slave node, do this.</p>
<pre class="brush: bash; title: ; notranslate">
firewall-cmd --permanent --zone=public --add-rich-rule=' 
  rule family=&quot;ipv4&quot; 
  source address=&quot;67.205.160.87/32&quot; 
  port protocol=&quot;tcp&quot; port=&quot;953&quot; accept'
</pre>
<p>Reload the rules on both.</p>
<pre class="brush: bash; title: ; notranslate">
firewall-cmd --reload
</pre>
<p>Restart BIND on both.</p>
<pre class="brush: bash; title: ; notranslate">
systemctl restart named
</pre>
<p>Now, you can manage them with rndc.</p>
<pre class="brush: bash; title: ; notranslate">
rndc reload
rndc status
</pre>
<p>From the master server, try to reload the slave server.</p>
<pre class="brush: bash; highlight: [1]; title: ; notranslate">
rndc -s 104.248.184.142 reload
server reload successful
</pre>
<p>What we also want to do is tell the OS that from now on, the default DNS server will be our local DNS.<br />
So, edit <strong>/etc/resolv.conf</strong> and add this line as the first line on both. </p>
<pre class="brush: bash; title: ; notranslate">
nameserver 127.0.0.1
</pre>
<p>If we try to ping google.com we should get a response or at least an IP resolved. That&#8217;s good. From another computer, try to use any of our servers as a DNS. This is what you should get: Query refused. That&#8217;s good too, because we don&#8217;t want our server to be used as a DNS server for other domains. We want to access the Internet from the server, e.g. to update the server, so we need to be able to use the local server to resolve any domains but only from localhost. </p>
<pre class="brush: bash; highlight: [1,5,9]; title: ; notranslate">
C:\Users\klimenta&gt;nslookup
Default Server:  google-public-dns-a.google.com
Address:  8.8.8.8

&gt; server 67.205.160.87
Default Server:  &#x5B;67.205.160.87]
Address:  67.205.160.87

&gt; www.google.com
Server:  &#x5B;67.205.160.87]
Address:  67.205.160.87

*** &#x5B;67.205.160.87] can't find www.google.com: Query refused
</pre>
<p>You can allow this server to act as a forwarder by including <strong>recursion yes</strong>; option under <strong>options </strong>and <strong>allow-access</strong> to all IPs (0.0.0.0/0), but that&#8217;s not the intended use of an authoritative DNS server. </p>
<h1>Zone file</h1>
<p>Now that we have the servers up and running, let&#8217;s create the zone file. The zone file tells where the records can be found. On the master server only, edit <strong>named.conf</strong> and add these two lines right after the <strong>listen-on</strong> option. We are allowing the transfer of the zones to the slave server only</p>
<pre class="brush: bash; title: ; notranslate">
allow-transfer { localhost; 104.248.184.142; };
notify yes;
</pre>
<p>Go all the way at the bottom and add these line to define the zone file.<br />
<strong>NOTE:</strong> If you have SELinux enabled, you can&#8217;t define your zone anywhere. Make sure you use <strong>/var/named</strong> for your zone file.).</p>
<pre class="brush: bash; title: ; notranslate">
zone &quot;cloudwerk.us&quot; {
        type master;
        file &quot;/var/named/db.cloudwerk.us&quot;;
};
</pre>
<p>Now, go to the <strong>/var/named </strong>directory and create the zone file to look like this. The file should be called <strong>db.cloudwerk.us</strong>. Do this on the master server only. You might want to read the following <a href="https://help.dyn.com/how-to-format-a-zone-file" rel="noopener noreferrer" target="_blank">link </a>if you are not familiar with the syntax of a zone file. </p>
<pre class="brush: bash; title: ; notranslate">
$TTL    604800
@       IN      SOA     ns1.cloudwerk.us.       admin.cloudwerk.us. (
                        2018121901;     Serial
                        3H;             Refresh
                        15M;            Retry
                        2W;             Expiry
                        1D );           Minimum

; name servers - NS records
        IN      NS      ns1.cloudwerk.us.
        IN      NS      ns2.cloudwerk.us.

; name servers - A records
ns1.cloudwerk.us.       IN      A       67.205.160.87
ns2.cloudwerk.us.       IN      A       104.248.184.142

; other servers - A records
www.cloudwerk.us.       IN      A       52.71.63.84
</pre>
<p>All you have to do now is to reload the new config with <strong>rndc reload</strong>. At this point we have the master server up and running. Now, we have to configure the slave server. Edit the <strong>named.conf</strong> file and add these lines at the bottom. Very self-explanatory. </p>
<pre class="brush: bash; title: ; notranslate">
zone &quot;cloudwerk.us&quot; {
        type slave;
        masters { 67.205.160.87; };
        file &quot;/var/named/slaves/db.cloudwerk.us&quot;;
};
</pre>
<p>Restart the <strong>named </strong>daemon and if you go to <strong>/var/named/slaves</strong> directory, you&#8217;ll see that the zone file replicated from the master. Finally, on both servers you have to allow the queries from the Internet. Edit <strong>named.con</strong>f and comment this line.</p>
<pre class="brush: bash; title: ; notranslate">
//allow-query     { localhost; }; 
</pre>
<p>Reload with <strong>rndc reload</strong> on both after.<br />
At this point, we have both the master and the slave servers configured, up and running. But no one on the Internet knows that our servers are authoritative servers. You have to make this change at your domain registrant. In my case, I&#8217;ve purchased the domain from Go Daddy, so I went to the DNS management panel and added two A records for ns1.cloudwerk.us and ns2.cloudwerk.us. Then, at the bottom of the web control panel, I&#8217;ve changed the DNS from xy.domaincontrol.com to custom and added my servers. I&#8217;ve encountered some issues, but the on-line chat with the support resolved this in 5 minutes. In essence, if you open up the DNS console, scroll all the way down and under <strong>Advanced Features</strong>, you&#8217;ll see <strong>Host names</strong> link. Click on this one and create two records, ns1 and ns2 with your IPs. Now, you can switch to <strong>Custom Nameserves</strong> on the same page.<br />
Leave some time for replication. It might take up to 24 hrs, but in my case it took less than 20 mins.<br />
You should know that you are in charge when these commands return your servers. In Windows:</p>
<pre class="brush: bash; highlight: [1,5,6,19,20]; title: ; notranslate">
C:\Users\klimenta&gt;nslookup
Default Server:  google-public-dns-a.google.com
Address:  8.8.8.8

&gt; set query=soa
&gt; cloudwerk.us
Server:  google-public-dns-a.google.com
Address:  8.8.8.8

Non-authoritative answer:
cloudwerk.us
        primary name server = ns1.cloudwerk.us
        responsible mail addr = admin.cloudwerk.us
        serial  = 2018121901
        refresh = 10800 (3 hours)
        retry   = 900 (15 mins)
        expire  = 1209600 (14 days)
        default TTL = 86400 (1 day)
&gt; set query=ns
&gt; cloudwerk.us
Server:  google-public-dns-a.google.com
Address:  8.8.8.8

Non-authoritative answer:
cloudwerk.us    nameserver = ns1.cloudwerk.us
cloudwerk.us    nameserver = ns2.cloudwerk.us
</pre>
<p>In Linux/BSD if you use <strong>dig</strong>:</p>
<pre class="brush: bash; highlight: [1]; title: ; notranslate">
dig +short NS cloudwerk.us
ns2.cloudwerk.us.
ns1.cloudwerk.us.
</pre>
<p>Or, if you want to do it <a href="https://mxtoolbox.com/dnscheck.aspx" rel="noopener noreferrer" target="_blank">on-line</a>.<br />
This is what I got.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2018/12/P118-01.png"><img fetchpriority="high" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2018/12/P118-01.png" alt="" width="1342" height="412" class="aligncenter size-full wp-image-8296" /></a><br />
It says that the slave server is leaking the zone which means anyone can list all the records. In order to prevent that, we have to edit <strong>named.conf</strong> on the slave server and add this line after <strong>listen-on </strong>option.</p>
<pre class="brush: bash; title: ; notranslate">
allow-transfer { localhost; 67.205.160.87; };
</pre>
<p>Do <strong>rndc reload</strong> after and if you re-execute the test, you&#8217;ll see that everything looks OK.</p>
<h1>DNSSEC (optional)</h1>
<p>I won&#8217;t go into details of what is DNSSEC, I&#8217;ll just explain how to configure and secure your DNS server. It&#8217;s pretty much a PKI infrastructure for securing your records by signing them with a private key. If you need more info, you can find tons of info by googling DNSSEC.<br />
On the master server, add this line after <strong>dnssec-validation yes;</strong> option in <strong>named.conf</strong>.</p>
<pre class="brush: bash; title: ; notranslate">
key-directory &quot;/var/named/keys&quot;;
</pre>
<p>On the slave server don&#8217;t do anything.<br />
Add these lines in the same file (named.conf) on the master server  only. They should be below <strong>file </strong>directive where your zone is defined (at the bottom of the file). These lines are part of your zone config, not separate directives.</p>
<pre class="brush: bash; title: ; notranslate">
auto-dnssec maintain;
inline-signing yes;
</pre>
<p>Let&#8217;s create the KSK and ZSK keys. Master server only.</p>
<pre class="brush: bash; title: ; notranslate">
cd /var/named/keys
dnssec-keygen -r /dev/urandom -a RSASHA256 -b 2048 -f KSK -n ZONE cloudwerk.us
ls -l
echo &quot;Take a note of the key file that ends with .key&quot;
dnssec-keygen -r /dev/urandom -a RSASHA256 -b 2048 -n ZONE cloudwerk.us
</pre>
<p>You&#8217;ll see 4 files created. Scribble down the first key file that was created (.key), see the output from above. Reload the config on the master but make sure BIND can access the keys.</p>
<pre class="brush: bash; title: ; notranslate">
chown -R named:named /var/named/keys
rndc reload
</pre>
<p>You&#8217;ll see two more files (.jbk and .signed) under <strong>/var/named</strong>. These are the signed files. If you check the <strong>slaves </strong>directory on the slave node, you&#8217;ll see a signed file there as well.<br />
Let&#8217;s do a test. Go to this <a href="https://dnssec-analyzer.verisignlabs.com/" rel="noopener noreferrer" target="_blank">link</a>, type your domain name and hit enter.<br />
You should see something like this.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2018/12/P118-02.png"><img decoding="async" src="https://blog.andreev.it/wp-content/uploads/2018/12/P118-02.png" alt="" width="717" height="763" class="aligncenter size-full wp-image-8297" /></a><br />
Now, stop the master server with <strong>rndc stop</strong> and refresh the web page. The test will take a little bit longer, because NS1 is down, but eventually you&#8217;ll get something like this.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2018/12/P118-03.png"><img decoding="async" src="https://blog.andreev.it/wp-content/uploads/2018/12/P118-03.png" alt="" width="796" height="782" class="aligncenter size-full wp-image-8298" /></a><br />
That&#8217;s normal. It tells us that ns1 is down. What&#8217;s not normal is the red X mark that says <strong>&#8220;No DS records found for coudwerk.us in the us zone&#8221;</strong>. This translates as, yes you signed your zone, but no one can validate it. It&#8217;s like a fake certificate. So, we need to tell our registrant that we really own the domain and that we signed it.<br />
This portion is also registrant&#8217;s  dependent. I&#8217;ll describe how to overcome this error with Go Daddy.<br />
So, go to the <strong>keys </strong>directory and execute this command against the first file, that one that you took note about. </p>
<pre class="brush: bash; highlight: [1]; title: ; notranslate">
cd /var/named/keys
dnssec-dsfromkey Kcloudwerk.us.+008+23956.key
cloudwerk.us. IN DS 23956 8 1 2DA94FECA549E0A2B137FA6C64D09D2CBADF8864
cloudwerk.us. IN DS 23956 8 2 8CC2CB79E1B8A6767F11230485C7499D52162135E1F6DAA503ADEC4470E417A9
</pre>
<p>Now go to the DNS management panel for your domain at Go Daddy and you&#8217;ll see something like this. Click on <strong>DNSSEC</strong> and then click <strong>ADD</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2018/12/P118-04.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2018/12/P118-04.png" alt="" width="419" height="529" class="aligncenter size-full wp-image-8299" /></a><br />
Looks confusing but it&#8217;s very simple. Just look at the output from the <strong>dnssec-dsfromkey</strong> and add accordingly. You&#8217;ll have to add both hash values.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2018/12/P118-05.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2018/12/P118-05.png" alt="" width="800" height="573" class="aligncenter size-full wp-image-8300" /></a><br />
For <strong>Key Tag</strong> enter <strong>23956</strong>, <strong>Algorithm</strong> is <strong>8</strong>, <strong>Digest Type</strong> is <strong>1</strong>, <strong>Digest </strong>is the hash value and <strong>Key Data Algorithm</strong> is also <strong>8</strong>, the value of <strong>Algorithm</strong>. Click <strong>Update </strong>, do the 2nd line of the output and wait 30-45 mins. Sometimes, even more. It depends on your registrant.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2018/12/P118-06.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2018/12/P118-06.png" alt="" width="861" height="892" class="aligncenter size-full wp-image-8301" /></a><br />
At the end it should look like this.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2018/12/P118-07.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2018/12/P118-07.png" alt="" width="1478" height="325" class="aligncenter size-full wp-image-8302" /></a><br />
And if you analyze your domain again, the result should look like this.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2018/12/P118-08.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2018/12/P118-08.png" alt="" width="713" height="929" class="aligncenter size-full wp-image-8303" /></a><br />
Or if you use dig, use the Google&#8217;s DNS server to check.</p>
<pre class="brush: bash; title: ; notranslate">
dig +trace +noadditional DS cloudwerk.us. @8.8.8.8 | grep DS
</pre>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.andreev.it/2018/12/141-centos-install-an-authoritative-dns-server-bind/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>FreeBSD: Install an authoritative DNS server (BIND)</title>
		<link>https://blog.andreev.it/2018/10/137-freebsd-install-an-authoritative-dns-server-bind/</link>
					<comments>https://blog.andreev.it/2018/10/137-freebsd-install-an-authoritative-dns-server-bind/#respond</comments>
		
		<dc:creator><![CDATA[Kliment Andreev]]></dc:creator>
		<pubDate>Tue, 23 Oct 2018 14:13:54 +0000</pubDate>
				<category><![CDATA[FreeBSD]]></category>
		<category><![CDATA[BIND]]></category>
		<category><![CDATA[DNS]]></category>
		<category><![CDATA[freebsd]]></category>
		<guid isPermaLink="false">https://blog.andreev.it/?p=4096</guid>

					<description><![CDATA[In this post I&#8217;ll explain how to install and configure BIND DNS server to&#8230;]]></description>
										<content:encoded><![CDATA[<div id="bsf_rt_marker"></div><p>In this post I&#8217;ll explain how to install and configure BIND DNS server to act as an authoritative server for a public domain in a master/slave configuration. This is not a setup for a server that will act as a DNS server in your local environment and does DNS resolution for your local network. In this post, the DNS server won&#8217;t resolve any DNS queries except for the domain that it is authoritative for. The domain that I&#8217;ll use is <strong>cloudwerk.us</strong> registered with Go Daddy, so some of the configurations will apply to Go Daddy only. The IPs and keys that I&#8217;ll use will be visible. The setup will be gone by the time you read this.<br />
So, I have my master server, <strong>ns1.cloudwerk.us (104.248.47.54)</strong> and the slave server <strong>ns2.cloudwerk.us (142.93.201.231)</strong>.<br />
I will be using FreeBSD 11.2 and BIND 9.12.2-P2. Before you start, make sure you have your domain purchased and you have 2 servers with public IPs up and running. You can leave the default registrant&#8217;s DNS servers for now. </p>
<h1>Installation, startup and control</h1>
<p>First, I&#8217;ll install BIND on both servers. All commands below are executed as root.</p>
<pre class="brush: bash; title: ; notranslate">
pkg install bind912
</pre>
<p>When the installation is done after 10-15 seconds, you&#8217;ll see some text that requires attention. I am not using a jailed install, so I can skip that part. The only part that&#8217;s important is to create the key for the <strong>rndc (Remote Name Daemon Control) </strong>utility. This utility allows management of the <strong>named </strong>(DNS) daemon. Moreover, you can manage remote DNS servers and I&#8217;ll explain how. So, let&#8217;s create the keys (highlighted line is what you type, the rest is output). Do this on the master server only.</p>
<pre class="brush: bash; highlight: [1]; title: ; notranslate">
rndc-confgen -a
wrote key file &quot;/usr/local/etc/namedb/rndc.key&quot;
</pre>
<p>As you can see, there is a file called <strong>rndc.key</strong> created under <strong>/usr/local/etc/namedb</strong> directory. This is the default directory where BIND expects to find its config files and zones.<br />
Now, copy this file to the second server in the same location. You can use scp, copy &#038; paste in a terminal session, it doesn&#8217;t matter. What matters is that you have to change the permissions and the owner of the file. BIND runs under the <strong>bind </strong>user, not root. Do this on both servers. </p>
<pre class="brush: bash; title: ; notranslate">
cd /usr/local/etc/namedb
chown root:bind rndc.key
chmod 640 rndc.key
</pre>
<p>Let&#8217;s make sure that BIND starts on boot. On both servers, execute:</p>
<pre class="brush: bash; title: ; notranslate">
sysrc named_enable=&quot;YES&quot;
</pre>
<p>Now, we can start the BIND daemon on both. </p>
<pre class="brush: bash; title: ; notranslate">
service named start
</pre>
<p>Check the logs.</p>
<pre class="brush: bash; highlight: [1]; title: ; notranslate">
tail /var/log/messages
Oct 22 15:11:11 ns1 named&#x5B;1161]: ----------------------------------------------------
Oct 22 15:11:11 ns1 named&#x5B;1161]: BIND 9 is maintained by Internet Systems Consortium,
Oct 22 15:11:11 ns1 named&#x5B;1161]: Inc. (ISC), a non-profit 501(c)(3) public-benefit
Oct 22 15:11:11 ns1 named&#x5B;1161]: corporation.  Support and training for BIND 9 are
Oct 22 15:11:11 ns1 named&#x5B;1161]: available at https://www.isc.org/support
Oct 22 15:11:11 ns1 named&#x5B;1161]: ----------------------------------------------------
Oct 22 15:11:11 ns1 named&#x5B;1161]: command channel listening on 127.0.0.1#953
Oct 22 15:11:11 ns1 named&#x5B;1161]: command channel listening on ::1#953
Oct 22 15:11:11 ns1 named&#x5B;1161]: all zones loaded
Oct 22 15:11:11 ns1 named&#x5B;1161]: running
</pre>
<p>We can&#8217;t start the server with the <strong>rndc </strong>utility, but we can stop it if needed with <strong>rndc stop</strong> or simply <strong>service named stop</strong>.<br />
To control the slave server from the master, we have to modify the main BIND configuration file, <strong>named.conf</strong> on the slave server. Also, the keys have to be the same, but we already took care of that part above.<br />
So, in the same <strong>/usr/local/etc/namedb</strong> directory, edit <strong>named.conf</strong> and add these lines, right before the options directive. Do this on the slave server, not the master.</p>
<pre class="brush: bash; title: ; notranslate">
include &quot;/usr/local/etc/namedb/rndc.key&quot;;

controls {
        inet 127.0.0.1 allow { localhost; } keys { &quot;rndc-key&quot;; };
        inet 142.93.201.231 allow { 104.248.47.54; } keys { &quot;rndc-key&quot;; };
};
</pre>
<p>If you look at my IPs below, this means that the rndc utility will be accepted from the localhost and from the the IP 104.248.47.54 which is the master server. But, we also have to tell BIND to listen on the public IP. By default, it listens on the <strong>localhost </strong>only.<br />
Do this on BOTH servers. In <strong>named.conf</strong> find the <strong>options </strong>directive and modify the <strong>listen-on</strong> option so it looks like this. You should put the public IP of each server there, so the line will differ on both servers. </p>
<pre class="brush: bash; title: ; notranslate">
//Master server
listen-on       { 127.0.0.1; 104.248.47.54; };
</pre>
<pre class="brush: bash; title: ; notranslate">
//Slave server
listen-on       { 127.0.0.1; 142.93.201.231; };
</pre>
<p>Restart BIND on both.</p>
<pre class="brush: bash; title: ; notranslate">
service named restart
</pre>
<p>Now, you can manage them with rndc.</p>
<pre class="brush: bash; title: ; notranslate">
rndc reload
rndc status
</pre>
<p>From the master server, try to reload the slave server.</p>
<pre class="brush: bash; title: ; notranslate">
rndc -s 142.93.201.231 reload
server reload successful
</pre>
<p>If you have a firewall, make sure port 953 TCP is open for communication.<br />
What we also want to do is tell the OS that from now on, the default DNS server will be our local DNS.<br />
So, edit <strong>/etc/resolv.conf</strong> and add this line as the first line on both. </p>
<pre class="brush: bash; title: ; notranslate">
nameserver 127.0.0.1
</pre>
<p>If we try to ping google.com we should get a response or at least an IP resolved. That&#8217;s good. From another computer, try to use any of our servers as a DNS. This is what you should get: Query refused. That&#8217;s good too, because we don&#8217;t want our server to be used as a DNS server for other domains. But, also, we want to access the Internet from the server, for example to update the server. Name resolution for other domains from localhost is OK, but not OK from outside. </p>
<pre class="brush: bash; highlight: [1,5,9]; title: ; notranslate">
C:\Users\Elite&gt;nslookup
Default Server:  ns-cache.above.net
Address:  207.126.96.248

&gt; server 142.93.201.231
Default Server:  ns2.cloudwerk.us
Address:  142.93.201.231

&gt; www.google.com
Server:  ns2.cloudwerk.us
Address:  142.93.201.231

*** ns2.cloudwerk.us can't find www.google.com: Query refused
</pre>
<p>You can allow this server to act as a forwarder by including <strong>recursion yes</strong>; option under <strong>options </strong>and <strong>allow-access</strong> to all IPs, but that&#8217;s not the intended use of an authoritative DNS server. </p>
<h1>Zone file</h1>
<p>Now that we have the servers up and running, let&#8217;s create the zone file. The zone file tells where the records can be found. On the master server only, edit <strong>named.conf</strong> and add these two lines right after the <strong>listen-on</strong> option. We are allowing the transfer of the zones to the slave server only</p>
<pre class="brush: bash; title: ; notranslate">
allow-transfer { localhost; 142.93.201.231; };
notify yes;
</pre>
<p>Go all the way at the bottom and add these line to define the zone file.<br />
<strong>NOTE:</strong> If you don&#8217;t want to use the dynamic directory, make sure that your zone file directory is owned by the <strong>bind </strong>user and group (e.g. <em>mkdir somedir, chown -R bind:bind somedir</em>).</p>
<pre class="brush: bash; title: ; notranslate">
zone &quot;cloudwerk.us&quot; {
        type master;
        file &quot;/usr/local/etc/namedb/dynamic/db.cloudwerk.us&quot;;
};
</pre>
<p>Now, go to the <strong>/usr/local/etc/namedb/dynamic </strong>directory and create the zone file to look like this. The file should be called <strong>db.cloudwerk.us</strong>. Do this on the master server only. You might want to read the following <a href="https://help.dyn.com/how-to-format-a-zone-file" rel="noopener noreferrer" target="_blank">link </a>if you are not familiar with the syntax of a zone file. </p>
<pre class="brush: bash; title: ; notranslate">
$TTL    604800
@       IN      SOA     ns1.cloudwerk.us.       admin.cloudwerk.us. (
                        2018101901;     Serial
                        3H;             Refresh
                        15M;            Retry
                        2W;             Expiry
                        1D );           Minimum

; name servers - NS records
        IN      NS      ns1.cloudwerk.us.
        IN      NS      ns2.cloudwerk.us.

; name servers - A records
ns1.cloudwerk.us.       IN      A       104.248.47.54
ns2.cloudwerk.us.       IN      A       142.93.201.231

; other servers - A records
www.cloudwerk.us.       IN      A       52.71.63.84
</pre>
<p>All you have to do now is to reload the new config with <strong>rndc reload</strong>. At this point we have the master server up and running. Now, we have to configure the slave server. Edit the <strong>named.conf</strong> file and add these lines at the bottom. Very self-explanatory. </p>
<pre class="brush: bash; title: ; notranslate">
zone &quot;cloudwerk.us&quot; {
        type slave;
        masters { 104.248.47.54; };
        file &quot;/usr/local/etc/namedb/dynamic/db.cloudwerk.us&quot;;
};
</pre>
<p>Restart the <strong>named </strong>daemon and if you go to <strong>/usr/local/etc/namedb/dynamic</strong> directory, you&#8217;ll see that the zone file replicated from the master.<br />
At this point, we have both the master and the slave servers configured, up and running. But no one on the Internet knows that our servers are authoritative servers. You have to make this change at your domain registrant. In my case, I&#8217;ve purchased the domain from Go Daddy, so I went to the DNS management panel and add two A records for ns1.cloudwerk.us and ns2.cloudwerk.us. Then, at the bottom of the web contol panel, I&#8217;ve changed the DNS from xy.domaincontrol.com to custom and added my servers. I&#8217;ve encountered some issues, but the on-line chat with the support resolved this in 5 minutes. In essence, if you open up the DNS console, scroll all the way down and under <strong>Advanced Features</strong>, you&#8217;ll see <strong>Host names</strong> link. Click on this one and create two records, ns1 and ns2 with your IPs. Now, you can switch to <strong>Custom Nameserves</strong> on the same page.<br />
Leave some time for replication. It might take up to 24 hrs, but in my case it took less than 20 mins.<br />
You should know that you are in charge when these commands return your servers. In Windows:</p>
<pre class="brush: bash; highlight: [1,5,6]; title: ; notranslate">
C:\Users\Elite&gt;nslookup
Default Server:  ns-cache.above.net
Address:  207.126.96.248

&gt; set query=soa
&gt; cloudwerk.us
Server:  ns-cache.above.net
Address:  207.126.96.248

Non-authoritative answer:
cloudwerk.us
        primary name server = ns1.cloudwerk.us
        responsible mail addr = admin.cloudwerk.us
        serial  = 2018101901
        refresh = 10800 (3 hours)
        retry   = 900 (15 mins)
        expire  = 1209600 (14 days)
        default TTL = 86400 (1 day)

cloudwerk.us    nameserver = ns2.cloudwerk.us
cloudwerk.us    nameserver = ns1.cloudwerk.us
ns1.cloudwerk.us        internet address = 104.248.47.54
ns2.cloudwerk.us        internet address = 149.93.201.231
</pre>
<p>In Linux/BSD if you use <strong>dig</strong>:</p>
<pre class="brush: bash; highlight: [1]; title: ; notranslate">
dig +short NS cloudwerk.us
ns2.cloudwerk.us.
ns1.cloudwerk.us.
</pre>
<p>Or, if you want to do it <a href="https://mxtoolbox.com/dnscheck.aspx" rel="noopener noreferrer" target="_blank">on-line</a>.<br />
This is what I got.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2018/10/P114-01.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2018/10/P114-01.png" alt="" width="1482" height="764" class="aligncenter size-full wp-image-8279" /></a><br />
It says that the slave server is leaking the zone which means anyone can list all the records. In order to prevent that, we have to edit <strong>named.con</strong>f on the slave server and add this line after <strong>listen-on </strong>option.</p>
<pre class="brush: bash; title: ; notranslate">
allow-transfer { localhost; 104.248.47.54; };
</pre>
<p>Do <strong>rndc reload</strong> after and if you re-execute the test, you&#8217;ll see that everything looks OK.</p>
<h1>DNSSEC (optional)</h1>
<p>I won&#8217;t go into details of what is DNSSEC, I&#8217;ll just explain how to configure and secure your DNS server. It&#8217;s pretty much a PKI infrastructure for securing your records by signing them with a private key. If you need more info, you can find tons of info by googling DNSSEC.<br />
On the master server, add these lines after <strong>listen-on</strong> option in <strong>named.conf</strong>.</p>
<pre class="brush: bash; title: ; notranslate">
dnssec-enable yes;
key-directory &quot;/usr/local/etc/namedb/keys&quot;;
</pre>
<p>On the slave server, add this line after <strong>listen-on</strong> option in <strong>named.conf</strong>.</p>
<pre class="brush: bash; title: ; notranslate">
dnssec-enable yes;
</pre>
<p>Add these lines in the same file on the master server  only. They should be below <strong>file </strong>directive where your zone is defined (at the bottom of the file).</p>
<pre class="brush: bash; title: ; notranslate">
auto-dnssec maintain;
inline-signing yes;
</pre>
<p>On the master server only, create they <strong>keys </strong>directory.</p>
<pre class="brush: bash; title: ; notranslate">
mkdir /usr/local/etc/namedb/keys
cd /usr/local/etc/namedb/keys
</pre>
<p>Let&#8217;s create the KSK and ZSK keys. Master server only.</p>
<pre class="brush: bash; title: ; notranslate">
dnssec-keygen -r /dev/urandom -a RSASHA256 -b 2048 -f KSK -n ZONE cloudwerk.us
ls -l
echo &quot;Take a note of the key file&quot;
dnssec-keygen -r /dev/urandom -a RSASHA256 -b 2048 -n ZONE cloudwerk.us
</pre>
<p>You&#8217;ll see 4 files created. Scribble down the first key file that was created, see the output from above. Step one directory up and change the ownership so BIND can read these files.</p>
<pre class="brush: bash; title: ; notranslate">
cd /usr/local/etc/namedb
chown -R bind:bind keys
rndc reload
</pre>
<p>If you go to the <strong>dynamic </strong>directory where your zone file is, you&#8217;ll see three more files. These are the signed files.</p>
<pre class="brush: bash; title: ; notranslate">
ls -l /usr/local/etc/namedb/dynamic
</pre>
<p>If you go on the slave server in the same <strong>dynamic </strong>directory, you&#8217;ll see that signed <strong>.jnl</strong> file also transferred.<br />
Let&#8217;s do a test. Go to this <a href="https://dnssec-analyzer.verisignlabs.com/" rel="noopener noreferrer" target="_blank">link</a>, type your domain name and hit enter.<br />
You should see something like this.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2018/10/P114-02.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2018/10/P114-02.png" alt="" width="470" height="519" class="aligncenter size-full wp-image-8280" /></a><br />
Now, stop the master server with <strong>rndc stop</strong> and refresh the web page. The test will take a little bit longer, because NS1 is down, but eventually you&#8217;ll get something like this.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2018/10/P114-03.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2018/10/P114-03.png" alt="" width="504" height="540" class="aligncenter size-full wp-image-8281" /></a><br />
That&#8217;s normal. It tells us that ns1 is down. What&#8217;s not normal is the red X mark that says <strong>&#8220;No DS records found for coudwerk.us in the us zone&#8221;</strong>. This translates as, yes you signed your zone, but no one can validate it. It&#8217;s like a fake certificate. So, we need to tell our registrant that we really own the domain and that we signed it.<br />
This portion is also registrant&#8217;s  dependent. I&#8217;ll describe how to overcome this error with Go Daddy.<br />
So, go to the <strong>keys </strong>directory and execute this command against the first file. </p>
<pre class="brush: bash; highlight: [1]; title: ; notranslate">
cd /usr/local/etc/namedb/keys
dnssec-dsfromkey Kcloudwerk.us.+008+23956.key
cloudwerk.us. IN DS 23956 8 1 2DA94FECA549E0A2B137FA6C64D09D2CBADF8864
cloudwerk.us. IN DS 23956 8 2 8CC2CB79E1B8A6767F11230485C7499D52162135E1F6DAA503ADEC4470E417A9
</pre>
<p>Now go to the DNS management panel for your domain at Go Daddy and you&#8217;ll see something like this. Click on <strong>DNSSEC</strong> and then click <strong>ADD</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2018/10/P114-04.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2018/10/P114-04.png" alt="" width="419" height="529" class="aligncenter size-full wp-image-8282" /></a><br />
Looks confusing but it&#8217;s very simple. Just look at the output from the <strong>dnssec-dsfromkey</strong> and add accordingly. You&#8217;ll have to add both hash values.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2018/10/P114-05.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2018/10/P114-05.png" alt="" width="800" height="573" class="aligncenter size-full wp-image-8283" /></a><br />
For <strong>Key Tag</strong> enter <strong>23956</strong>, <strong>Algorithm</strong> is <strong>8</strong>, <strong>Digest Type</strong> is <strong>1</strong>, <strong>Digest </strong>is the hash value and <strong>Key Data Algorithm</strong> is also <strong>8</strong>, the value of <strong>Algorithm</strong>. Click <strong>Update </strong>, do the 2nd line of the output and wait 30-45 mins. Sometimes, even more. It depends on your registrant.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2018/10/P114-06.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2018/10/P114-06.png" alt="" width="861" height="892" class="aligncenter size-full wp-image-8284" /></a><br />
At the end it should look like this.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2018/10/P114-07.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2018/10/P114-07.png" alt="" width="1478" height="325" class="aligncenter size-full wp-image-8285" /></a><br />
And if you analyze your domain again, the result should look like this.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2018/10/P114-08.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2018/10/P114-08.png" alt="" width="713" height="929" class="aligncenter size-full wp-image-8286" /></a><br />
Or if you use dig, use the Google&#8217;s DNS server to check.</p>
<pre class="brush: bash; title: ; notranslate">
dig +trace +noadditional DS cloudwerk.us. @8.8.8.8 | grep DS
</pre>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.andreev.it/2018/10/137-freebsd-install-an-authoritative-dns-server-bind/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
