DNS Open Root
In this article, we are going to create a DNS server with bind9. We will use this DNS server to create a new extension lastname
and resolve to n4n5.lastname
to an IP address.
This DNS server will be hosted on a local network with the IP address 192.168.1.69
. Commands on the server have a little icon on the right side.
First of all, we need the packages on the server.
sudo apt install dnsutils # install dig command
sudo apt install bind9 # install bind9 dns server
Retrieve the IP address of a domain
To start our little journey, we first need to know where the domain n4n5.dev points to. We can do this by finding the current ip of n4n5.dev
In DNS, a name is mapped to an IP address, this is called an A
record. We can find the IP address of a domain by using the dig
command.
dig n4n5.dev
;;...
;; ANSWER SECTION:
n4n5.dev. 3012 IN A 185.199.108.153
;;...
To see the full details of our DNS request, we can use the +trace
option.
dig n4n5.dev +trace
; <<>> DiG 9.18.30-0ubuntu0.24.04.2-Ubuntu <<>> +trace n4n5.dev
;; global options: +cmd
. 50946 IN NS d.root-servers.net.
. 50946 IN NS e.root-servers.net.
. 50946 IN NS f.root-servers.net.
. 50946 IN NS g.root-servers.net.
. 50946 IN NS h.root-servers.net.
. 50946 IN NS i.root-servers.net.
. 50946 IN NS j.root-servers.net.
. 50946 IN NS k.root-servers.net.
. 50946 IN NS l.root-servers.net.
. 50946 IN NS m.root-servers.net.
. 50946 IN NS a.root-servers.net.
. 50946 IN NS b.root-servers.net.
. 50946 IN NS c.root-servers.net.
;; Received 239 bytes from 127.0.0.53#53(127.0.0.53) in 17 ms
dev. 172800 IN NS ns-tld2.charlestonroadregistry.com.
dev. 172800 IN NS ns-tld5.charlestonroadregistry.com.
dev. 172800 IN NS ns-tld3.charlestonroadregistry.com.
dev. 172800 IN NS ns-tld1.charlestonroadregistry.com.
dev. 172800 IN NS ns-tld4.charlestonroadregistry.com.
;; Received 756 bytes from 2801:1b8:10::b#53(b.root-servers.net) in 304 ms
n4n5.dev. 10800 IN NS ns106.ovh.net.
n4n5.dev. 10800 IN NS dns106.ovh.net.
;; Received 329 bytes from 216.239.32.105#53(ns-tld1.charlestonroadregistry.com) in 21 ms
n4n5.dev. 3600 IN A 185.199.108.153
;; Received 249 bytes from 213.251.188.150#53(dns106.ovh.net) in 19 ms
We can see here the full path of our DNS request:
- We get the root servers
- lines end with
.root-servers.net
- lines end with
- We ask one root server (
2801:1b8:10::b#53(b.root-servers.net)
) about the authority servers for.dev
domain- it tells us to check with some
.charlestonroadregistry.com
servers
- it tells us to check with some
- We ask one
.dev
authority server (216.239.32.105#53(ns-tld1.charlestonroadregistry.com)
) for then4n5.dev
domain- it tells us to check with
ns106.ovh.net
ordns106.ovh.net
- it tells us to check with
- We ask the
213.251.188.150#53(dns106.ovh.net)
servers for the IP address ofn4n5.dev
- it tells us that the
A
record ofn4n5.dev
(the ip address) points to185.199.108.153
- it tells us that the
As my website is currently hosted with github pages, it means that 185.199.108.153
is an IP address of a github server.
This is correct! We can verify that on the page https://docs.github.com/en/pages/configuring-a-custom-domain-for-your-github-pages-site/managing-a-custom-domain-for-your-github-pages-site
DNS server setup
Now that we got the address, we can start to create our own DNS server.
Bind9 configuration files are located in /etc/bind/
. The main configuration file is /etc/bind/named.conf
which includes other configuration files.
sudo nano /etc/bind/named.conf.default-zones
// .. others zone
// name to ip conversion
zone "lastname" IN {
type master;
file "/etc/bind/db.lastname";
};
sudo nano /etc/bind/db.lastname
;
; BIND data file
;
$TTL 604800
@ IN SOA ns.lastname. root.lastname. (
2 ; Serial - increment this number each time you update the file
604800 ; Refresh - how often secondary DNS servers should check for updates.
86400 ; Retry - how often secondary servers retry if the primary is unreachable.
2419200 ; Expire - after this time, if the primary is still unreachable, the zone is considered invalid.
604800 ) ; Negative Cache TTL - this controls how long other servers cache no-such-domain (NXDOMAIN) responses from this server.
;
@ IN NS ns.lastname.
ns IN A 192.168.1.69
n4n5 IN A 185.199.108.153
We don’t forget to restart the bind9 service on the server
sudo service bind9 restart
Use the DNS server
The last step is to use our new DNS server! We can do this by changing the DNS server of our computer to the one we just created.
sudo nano /etc/resolv.conf
nameserver 192.168.1.69
# ... others parameters
Then we can check if our DNS server is working by using the host
command
host n4n5.lastname
n4n5.lastname has address 185.199.108.153
Or we can use the dig
command
dig n4n5.lastname
;; ..
;; ANSWER SECTION:
n4n5.lastname. 604800 IN A 185.199.108.153
Now, we can test with our browser or with curl
to see if our DNS server is working.
On our browser, we simply need to type n4n5.lastname/
(the slash is mandatory to force the browser to accept this url - since this extension does not exist) and we should see our website.
But that’s not the case! First of all, we see that the website is not secure, it’s related to the certificate not being valid for this domain. We can ignore this warning (see last paragraph) and continue to the website.
And that’s still not the case! A Github 404 page is displayed!
This is because github as only a few addresses for many websites! To know which request is for which website, it checks the Host
header!
We could create a browser extension to add the
Host
header to the request, but let’s try withcurl
for now.
curl n4n5.lastname
<!DOCTYPE html>
<!-- Github Pages 404 error -->
</html>
We got 404! But now we know why! We need to add the Host
header to our request!
curl -H 'Host: n4n5.dev' n4n5.lastname
<html>
<head><title>301 Moved Permanently</title></head>
<body>
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx</center>
</body>
</html>
If we use the verbose option
-v
, we can see that the server is trying to redirect us to the secure version of the websitehttps://n4n5.dev
And it’s still not working! This is because Github wants to redirect us to the secure version of the website! Let’s try it!
curl -H 'Host: n4n5.dev' https://n4n5.lastname
curl: (60) SSL: no alternative certificate subject name matches target host name 'n4n5.lastname'
More details here: https://curl.se/docs/sslcerts.html
curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.
As expected, we get an error! This is because the certificate is not valid for this domain! We can ignore this warning by using the -k
option
curl -k -H 'Host: n4n5.dev' https://n4n5.lastname
<!DOCTYPE html>
<!-- n4n5.dev webpage -->
</html>
Yeah! The HTML of the website is displayed! Mission accomplished!
See also:
- https://bind9.readthedocs.io/ - bind9 documentation
- https://cr.yp.to/djbdns.html - djbdns
- https://letsencrypt.org/how-it-works/ - how certificates works
- Don’t forget to remove the
nameserver
from/etc/resolv.conf
Definitions:
SOA record: the first record in a DNS zone file and defines the authoritative information for the domain.
NS record (or nameserver record): is a DNS record that contains the name of the authoritative name server within a domain or DNS zone.
Setup reverse DNS
sudo nano /etc/bind/named.conf.default-zones
// .. others zone
// ip to name conversion
zone "1.168.192.in-addr.arpa" IN {
type master;
file "/etc/bind/db.192.168.1";
};
sudo nano /etc/bind/db.192.168.1
;
; BIND data file for reverse DNS
;
$TTL 604800
@ IN SOA ns.lastname. root.lastname. (
2 ; Serial
604800 ; Refresh
86400 ; Retry
2419200 ; Expire
604800 ) ; Negative Cache TTL
;
@ IN NS ns.
69 IN PTR ns.lastname.
69
is the last part of our ip address
Test reverse DNS
dig -x 192.168.1.69
;; ...
;; QUESTION SECTION:
;69.1.168.192.in-addr.arpa. IN PTR
;; ANSWER SECTION:
69.1.168.192.in-addr.arpa. 604800 IN PTR ns.lastname.
;; Query time: 22 msec
;; SERVER: 192.168.1.69#53(192.168.1.69) (UDP)
;; MSG SIZE rcvd: 134
The
-x
is a shortcut ofdig 69.1.168.192.in-addr.arpa PTR