How I hosted a DNS server on AWS ?

Wait. I know what you are thinking now.

Who on earth would do such a crazy thing ?

Why would a person even host a DNS server on AWS when one could use Route53 to efficiently manage DNS records.

The answer is simple:

I’ve been a user of DNS since my first interaction with the internet, but have no clear idea on how DNS works.

So I started learning how DNS works and more on how DNS server works. You can check out my notes on DNS. I felt that the best way to learn about DNS is by practically hosting a DNS server.

Trust me this way is far better than learning DNS by using a third party DNS service or reading theoretical blog posts on how DNS works.

I had a few credits left on AWS, that’s when I asked myself this question: “Is it possible to host a DNS server on AWS?”

Creating the Name Server on AWS

The steps are pretty simple:

  1. Create an EC2 instance. Free tier version of Ubuntu works fine. (Please read this article to learn how to create EC2 instance). Download the SSH key to access the instance.
  2. Create an elastic IP and associate it with the EC2 instance created in the first step. (If you have never worked with elastic IPs, you can read this article)
  3. Now the public IP of the EC2 instance will be replaced by the elastic IP.
  4. Create a Security Group which allows access to port 53 (TCP and UDP) and add this security group to the EC2 instance. This allows DNS interactions from public internet.

Setting up the domain name

I didn’t really want to spend money for this experiment. So ended up registering a free domain – – for one month at FreeNom.

Did you know ? Machane is the malayalam slang word meaning “dude”

FreeNom allows user managed DNS name servers. One could create Glue records at the beginning of the registration. I entered two nameservers as and and gave the same AWS elastic IP in both the IP address fields.

If you observe above, you can see that I am in the process of registering and provided the nameservers as and That’s the trick in glue records. So, basically we are saying the domain registrar that I am going to register and I am also going to host the nameservers for it under the DNS paths and

Once the registration of the domain is successful and logged in to the FreeNom domain nameserver administration panel, one should be able to see something similar to the following:

Setting up the DNS server

I have done the first half of the job. The domain registration is instant but the propagation of the domain’s DNS would take some time (upto 72 hours on FreeNom). In the mean time I could setup the DNS server.

After much fiddling with the installation and configuration of BIND9 DNS server on Ubuntu, I finally created a bash script to automate the setup of DNS zones using BIND server.

If you are interested in setting up a DNS server, please make changes (domain name, subdomains, elastic IP, etc) to the following script. Also don’t forget to run it with sudo permission.

apt install bind9 bind9-doc -y

echo 'include "/etc/bind/named.conf.log";' | tee -a /etc/bind/named.conf

# Store all the logs to /var/log/named/bind.log

tee /etc/bind/named.conf.log << EOF
logging {
 channel bind_log {
   file "/var/log/named/bind.log" versions 3 size 5m;
   severity info;
   print-category yes;
   print-severity yes;
   print-time yes;
 category default { bind_log; };
 category update { bind_log; };
 category update-security { bind_log; };
 category security { bind_log; };
 category queries { bind_log; };
 category lame-servers { null; };

# Create the directory for storing logs

mkdir /var/log/named
chown bind:root /var/log/named
chmod 775 /var/log/named/

service bind9 restart

# Setup log rotation

tee /etc/logrotate.d/bind << EOF
    rotate 90
    dateformat _%Y-%m-%d
    create 644 bind bind
        /bin/systemctl reload bind9

# Change the zone to your domain name

tee /etc/bind/named.conf.local << EOF
zone "" {
        type master;
        file "/etc/bind/zones/";

mkdir /etc/bind/zones

# Creating the zone files
# Setting AWS elastic IP


# Please dont forget . at the end of the DNS entries

tee /etc/bind/zones/ << EOF
\$TTL 900
@       IN      SOA (
                                1       ;<serial-number>
                              900       ;<time-to-refresh>
                              900       ;<time-to-retry>
                           604800       ;<time-to-expire>
                              900)      ;<minimum-TTL>
;List Nameservers
        IN      NS
        IN      NS
;Create A record
        IN      A
;address to name mapping
ns1     IN      A       $ElasticIP
ns2     IN      A       $ElasticIP
;wildcard DNS entry
*       IN      A

service bind9 restart

In the above script, I have explicitly mentioned that and * (except the subdomains ns1 and ns2) resolve to Once the registered domain has propagated its DNS changes around the world, anyone could query the domain and its subdomains.

Final thoughts

I have finally created an authoritative DNS server which resolves any subdomain of It will not resolve DNS of any other domain.

I did this to experiment and learn more about how DNS works (in real life) and DNS servers. I gained a good experience and had a lot of fun along the learning process.

Until my next experiment, hasta la vista.

DISCLAIMER: I have registered the domain for experimental purpose for a single month. Any changes done to the domain’s DNS after a month (from the time of writing this article) will not be me. I am not be responsible for any damage done by reusing the above bash script.

Feel free to share this article:
Tweet 20

Leave a Reply

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