Monday, May 4, 2015

Deploying a DNS Server using Docker

http://www.damagehead.com/blog/2015/04/28/deploying-a-dns-server-using-docker

This is the first part of a series of how-to’s where I describe setting up and using various docker containers for home and production use.
To start off this series we will use the sameersbn/bind docker image to setup a DNS server in production and host only environments.
BIND, developed by the Internet Systems Consortium, is a production-grade and by far the most popular and widely used opensource DNS server software available.

Introduction

The Domain Name System (DNS) server takes a fully qualified domain name (FQDN) such as www.example.com and returns the corresponding IP address such as 93.184.216.34.
A couple of reasons to set up a DNS server.
By setting up a local DNS server you don’t rely on your ISP’s DNS servers which are often bogged down by incoming traffic which makes responses to DNS queries take longer to get serviced.
Besides performing domain name resolutions, a BIND server also acts as a DNS cache. This means that DNS queries could get serviced from the local cache. This in turn speeds up DNS responses.
Some ISP’s block access to websites by DNS spoofing. Setting up your own DNS server can help you get around this. However, a more effective way to circumvent this type of censorship is by using the tor browser which can be installed using the sameersbn/browser-box image.
Finally and most importantly, a local DNS server will enable you to define a domain for your local network. This allows you to address machines/services on the network with a name rather than its IP address. When setting up web services whether you do it using docker or otherwise, installing a DNS server makes the setup much simpler and easier to deal with.

Setting up the image

Begin by fetching the image from the docker hub.

1
docker pull sameersbn/bind:latest
Now lets “boot” the image…

1
2
3
4
5
docker run -d --name=bind --dns=127.0.0.1 \
  --publish=172.17.42.1:53:53/udp --publish=172.17.42.1:10000:10000 \
  --volume=/srv/docker/bind:/data \
  --env='ROOT_PASSWORD=SecretPassword' \
  sameersbn/bind:latest
Here is the gist of the equivalent configuration in docker-compose.yml form.
  • -d detaches, runs the container in the background
  • --name='bind' assigns the name bind to the container
  • --dns=127.0.0.1 configures the dns of the container to 127.0.0.1
  • --publish=172.17.42.1:53:53/udp makes the DNS server accessible on 172.17.42.1:53
  • --publish=172.17.42.1:10000:10000 makes webmin accessible at https://172.17.42.1:10000
  • --volume=/srv/docker/bind:/data mounts /srv/docker/bind as a volume for persistence
  • --env='ROOT_PASSWORD=SecretPassword' sets the root password to SecretPassword
In the above command the DNS server will only be accessible to the host and other containers over the docker bridge interface (host only). If you want the DNS server to be accessible over the network you should replace --publish=172.17.42.1:53:53/udp with --publish=53:53/udp (all interfaces) or something like --publish=192.168.1.1:53:53/udp (specific interface).
From this point on 172.17.42.1 will refer to our local DNS server. Replace it with the appropriate address depending on your setup.
The sameersbn/bind image includes webmin, a web-based interface for system administration, so that you can quickly and easily configure BIND. Webmin is launched automatically when the image is started.
If you prefer configuring BIND by hand, you can turn off webmin startup by setting --env='WEBMIN_ENABLED=false' in the run command. The BIND specific configuration will be available at /srv/docker/bind/bind. To apply your configuration send the HUP signal to the container using docker kill -s HUP bind
Finally, if --env='ROOT_PASSWORD=SecretPassword' is not specified in the run command, a random password is generated and assigned for the root user which can be retrieved with docker logs bind 2>&1 | grep '^User: ' | tail -n1. This password is used while logging in to the webmin interface.

Test the DNS server

Before we go any further, lets check if our DNS server is able to resolve addresses using the unix host command.

1
host www.google.com 172.17.42.1
  • www.google.com the address to resolve
  • 172.17.42.1 the DNS server to be used for the resolution
If everything works as expected the host command should return the IP address of www.google.com.

Using the DNS server

If you have setup a DNS server for your local network, you can configure your DHCP server to give out the DNS servers address in the lease responses. If you do not have a DHCP server running on your network (why?) you will have to manually configure it in the operating systems network settings.

Alternately, on linux distributions that use Network Manager (virtually every linux distribution), you can add a dnsmasq configuration (/etc/NetworkManager/dnsmasq.d/dnsmasq.conf) such that the local DNS server would be used for specific addresses, while the default DNS servers would be used otherwise.
1
2
3
4
5
6
domain-needed
all-servers
cache-size=5000
strict-order

server=/example.com/google.com/172.17.42.1
In the above example, regardless of the primary DNS configuration the DNS server at 172.17.42.1 will be used to resolve example.com and google.com addresses. This is particularly useful in host only configurations when you setup a domain to address various services on the local host without having to manually change the DNS configuration everytime you connect to a different network.
After performing the dnsmasq configuration the network manager needs to be restarted for the changes to take effect. On Ubuntu, this is achieved using the command restart network-manager
Finally, we can configure docker such that the containers are automatically configured to use our DNS server. This is done by adding --dns 172.17.42.1 to the docker daemon command. On Ubuntu, this is done at /etc/default/docker. The docker daemon needs to be restarted for these changes to take effect.

Creating a domain using webmin

Point your web browser to https://172.17.42.1:10000 and login to webmin as user root and password SecretPassword. Once logged in click on Servers and select BIND DNS Server.

This is where we will perform the DNS configuration. Changes to the configuration can be applied using the Apply Configuration link in the top right corner of the page. We will create a domain named example.com for demonstration purposes.
We start by creating the reverse zone 172.17.42.1. This is optional and required only if you want to be able to do reverse DNS (rDNS) lookups. A rDNS lookup returns the domain name that is associated with a given IP address. To create the zone select Create master zone and in the Create new zone dialog set the Zone type to Reverse, the Network address to your interface IP address 172.17.42.1, the Master server tons.example.com and finally set Email address to the domain administrator’s email address and select Create.

Next, we create the forward zone example.com by selecting Create master zone and in the Create new zone dialog set the Zone type to Forward, the Domain Name to example.com, the Master server to ns.example.com and set Email address to the domain administrator’s email address and select Create. Next, create the DNS entry for ns.example.com pointing to 172.17.42.1 and apply the configuration.

To complete this tutorial we will create a address (A) entry for webserver.example.com and then add a domain name alias (CNAME) entry www.example.com which will point to webserver.example.com.
To create the A entry, select the zone example.com and then select the Address option. Set the Name to webserver and the Address to 192.168.1.1. To create the CNAME entry, select the zone example.com and then select the Name Alias option. Set the Name to www and the Real Name to webserver and apply the configuration.

And now, the moment of truth…
1
2
host webserver.example.com 172.17.42.1
host www.example.com 172.17.42.1
These commands should return the DNS addresses as per our configuration. Time to find out.

And there you have it. A local DNS server with a local domain named example.com.

No comments:

Post a Comment