Wizardlab DNS Automation¶
As a development and training environment, Wizardlab has unique requirements for user configurability. Users need to be able to modify DNS parameters to suit a variety of projects.
Wizardlab is designed to operate in a production-like fashion through automated service setup and delivery. Wizardlab’s approach to DNS exemplifies these ideas. While there are specific downsides to containerizing DHCP (raw vs udp socket), DNS performs well as a container, so it’s the first Docker-based service that I developed for Wizardlab.
Connect to control:
$ vagrant ssh control
Setup Bind9, ISC DHCP, and Docker on the services
VM:
$ make docker_lab
Wizardlab’s DNS is configured by the infra
ansible role, which configures
Docker, DNS, and DHCP.
The infra
role leverages the docker
role to setup the docker engine.
setup_bind.yml
ensures wizardlab-bind9
is cloned to the services
VM, and the service is started with docker compose up -d
.
Wizardlab’s default domain is called wizardlab.test
.test
is a special .tld that will never be registered per
RFC 2606.
We setup resource records (RR) for ns1
, control
, and services
Name |
IP Address |
---|---|
ns1 |
varies |
control |
192.168.56.2 |
services |
192.168.56.3 |
Compose will assign a private ip address on a /24 network to the ns1 container.
For example, 172.18.0.2/24. build_file.py
will infer the container IP address and
add the value to the record for ns1.
To revise the DNS settings, cd
to /vagrant/wizardlab-bind9
and edit
bind/domain.json
or bind/options.json
then run:
$ sudo rebuild.sh
The DNS service will now be configured how you specified.
As a standalone project, we have a easily BIND9 service that runs on Docker, but combining ansible automation with these features gives me DNS service that I can reconfigure reliably as I add and remove services from my development/training environment.
Why BIND9¶
Wizardlab deploys BIND9 because it’s the reference implementation of the DNS protocol, it’s widely used and thoroughly tested, and it’s available on most distributions.
Why a Docker container?¶
DNS is a great service to run in a docker container. In production, docker containers make services easy to deploy and move between servers. With Wizardlab’s DNS service, I saw an opportunity to develop a side-project that could stand alone as a Docker project
Wizardlab-bind9¶
github.com/ashemath/wizardlab-bind9
Overview¶
This project will setup a BIND 9 DNS server using docker compose
.
While this project could be useful in other contexts, it’s primary
purpose is to serve as a repository for Wizardlab’s DNS service automation.
Motivation¶
I needed a DNS server to deliver authoritative DNS services for isolated training/development networks. Long term, I need something reliable that I can build on to manage DNS on private cloud provider networks.
Wizardlab-bind9 is my idea of using Docker and Python to accomplish this mission.
Design¶
Having a BIND server on Docker allows us to drive dns over a variety of
network interfaces. By default, this project will override host network ports
53/udp
and 53/tcp
. In a isolated network context, that’s probably what you
want, but please use caution.
Wizardlab-bind9 is designed so we can craft/modify the single domain.json
.
Specifying the domain name, forwarders, and all the records that we’d like
in that one file.
When the container starts, build_files.py
reads domain.json
and
options.json
, parses the requested properities of the domain, and stages up
the generated zones.*
, *.db
, and named.conf.*
files in the
/bind/etc_bind/
and bind/etc_bind/{primary,secondary}
subdirectories.
Next, the staged files are copied from /bind/etc_bind/*
to /etc/bind/
and the named
service is started with the command named -4 -g
.
The BIND service runs in the forground, so all the debug output gets caught
by Docker’s default logging service.
To summarize:
Edit
domain.json
Run
docker compose up -d
Profit.
There’s a bit of magic happening between domain.json
and the
build_files.py
command. The 2nd RR is overritten by a python
call that determines the assigned IP address for the container.
This means that the BIND server can add the appropriate “glue”
record reflecting the IP docker assigned the container.
What this means is that any IP you specify for rr_data for the 2nd
RR in the domain.json
file will be overwritten. This may not be
what you like, so feel free to edit build_file.py
if you do not
need this feature.
Current status¶
In it’s current form, it sets up a single domain effectively.
Domain name
, primary
zone status, acl groups, and as many resource records
as you need can be set up in the one domain.json
file.
Server settings that contribute to /etc/bind/named.conf.options
can be set in
the bind/options.json
file.
build_files.py
supports reading the options.json
and domain.json
files.
I am working on having it reconcile additional *.json
files, combining into
one or more configured “zones” that can run on a single container, but I
would like to focus on configuration that needs just the single SOA and a few
RRs for now.