Basic Building Blocks: Setting up bind in CentOS 7 for DNS

featured image retrieved from

I had the chance to buckle down and get some DNS servers running in the lab. The process, although not painless, was not terribly difficult, and the upshot is that my lab is far more scalable than it was previously. I used a good guide that I found at Unixmen.

First, a primer on DNS. We all use DNS and we know that it provides name resolution against IP addresses, resulting in a far easier way to access our favorite servers than remembering a set of numbers. What do the core components of DNS do? I am going to assume you know what an IP address, host name, FQDN, etc. mean, so here’s a quick vocabulary list for us to get started:

  • Name server: this is a system running DNS server software and is intended to provide name resolution. DNS server software may include Microsoft’s built-in DNS server or something like BIND. Speaking of BIND…
  • BIND: Stands for Berkeley Internet Name Domain. This is the software package that I used for my DNS servers.
  • Zone files: Text documents that associate names to IP addresses (and vice versa). Zone files contain records (another term) which determine what sort of servers those IP addresses are resolving to. We’ll talk about specific types of records shortly.

Now that we know what we’re talking about, how do we go about setting up BIND? First, start with installing a minimal CentOS 7 image.


You’re going to want to do this twice, assuming that you want a primary and secondary DNS server. Read the Unixmen guide above for the differences in slave setup; if you’re able to set up a master DNS server you will have no problem setting up a slave. A primary server will be sufficient for some, but I plan on abusing these systems a bit down the line.

With CentOS installed and running, assign the systems static IP addresses and make sure that they can access the internet. The tool you want to use in a minimal install of CentOS 7 is nmtui.


OS installed, networking set up and blinking… let’s install bind!

sudo yum install bind bind-utils -y

After that’s done, we need to edit /etc/named.conf.

[aschenck@dns1 ~]$ sudo cat /etc/named.conf
// named.conf
// Provided by Red Hat bind package to configure the ISC BIND named(8) DNS
// server as a caching only nameserver (as a localhost DNS resolver only).
// See /usr/share/doc/bind*/sample/ for example named configuration files.

options {
        listen-on port 53 {;;};
#       listen-on-v6 port 53 { ::1; };
        directory       "/var/named";
        dump-file       "/var/named/data/cache_dump.db";
        statistics-file "/var/named/data/named_stats.txt";
        memstatistics-file "/var/named/data/named_mem_stats.txt";
        allow-query     { localhost;;};
        allow-transfer  { localhost;;};

         - If you are building an AUTHORITATIVE DNS server, do NOT enable recursion.
         - If you are building a RECURSIVE (caching) DNS server, you need to enable
         - If your recursive DNS server has a public IP address, you MUST enable access
           control to limit queries to your legitimate users. Failing to do so will
           cause your server to become part of large scale DNS amplification
           attacks. Implementing BCP38 within your network would greatly
           reduce such attack surface
        recursion yes;

        dnssec-enable yes;
        dnssec-validation yes;

        /* Path to ISC DLV key */
        bindkeys-file "/etc/named.iscdlv.key";

        managed-keys-directory "/var/named/dynamic";

        pid-file "/run/named/";
        session-keyfile "/run/named/session.key";

logging {
        channel default_debug {
                file "data/";
                severity dynamic;

zone "." IN {
        type hint;
        file "";

zone "vlab.local" IN {
        type master;
        file "forward.vlab";
        allow-update { none; };

zone "" IN {
        type master;
        file "reverse.vlab";
        allow-update { none; };

include "/etc/named.rfc1912.zones";
include "/etc/named.root.key";


Everything in bold needs to be edited, or in the case of the allow-transfer line, added. What we are telling named.conf to do is listen for DNS traffic on our IP and port, allow for anyone on our subnet to query for DNS information, and transfer zone files to any specified slaves. Finally, we need to add references to our forward and reverse zone files. Obviously, change things like “vlab.local” to whatever your own personal private domain happens to be.

With /etc/named.conf ready, we now need to create  our zone files, located at /var/named/.

Start with the forward zone file.

[aschenck@dns1 ~]$ sudo cat /var/named/forward.vlab
[sudo] password for aschenck:
$TTL 86400
@   IN  SOA    dns1.vlab.local. root.vlab.local. (
        00001       ;Serial
        3600        ;Refresh
        1800        ;Retry
        604800      ;Expire
        86400       ;Minimum TTL
@       IN  NS        dns1.vlab.local.
@       IN  NS        dns2.vlab.local.
@       IN  A
@       IN  A
@       IN  A
dns1           IN  A
dns2           IN  A
aveproxy       IN  A
[aschenck@dns1 ~]$


Now, what the heck does all of this mean? Let’s go through it line by line:

  • $TTL 86400 – This specifies the time to live. This is the amount of time in seconds after which a DNS client must discard an old record and grab an updated version.
  • IN SOA – “Internet Start of Authority”
  • dns1.vlab.local. – Primary master domain server.
  • root.vlab.local. – Email address of administrator for this zone. The . after root automatically becomes a @.
  • Serial – This is an arbitrary number that must be incremented every time you update the zone file so that it propagates correctly.
  • Refresh – Amount of time slaves will wait before polling the master for changes.
  • Retry – Amount of time a slave will wait before polling the master in case it is unreachable.
  • Expire – Amount of time a slave will wait before no longer returning DNS results as authoritative in case of master failure.
  • Minimum TTL – Amount of time that the name server will cache an error if it cannot find the requested name.

Finally, let’s talk about the record types found in the forward zone file:

  • NS records: These are name servers. Notice that we have NS records for both dns1.vlab.local as well as dns2.vlab.local.
  • A records: These map a host to an IPv4 addresses. Notice I have records for three hosts, including the already-mentioned dns1 and dns2 hosts.

Our reverse zone file looks similar, but serves a different purpose. Forward lookups resolve hostnames to IP addresses; reverse lookups associate IP addresses to hostnames!

[aschenck@dns1 ~]$ sudo cat /var/named/reverse.vlab
[sudo] password for aschenck:
$TTL 86400
@   IN  SOA    dns1.vlab.local. root.vlab.local. (
        2011071001  ;Serial
        3600        ;Refresh
        1800        ;Retry
        604800      ;Expire
        86400       ;Minimum TTL
@       IN  NS        dns1.vlab.local.
@       IN  NS        dns2.vlab.local.
@       IN  PTR       vlab.local.
dns1        IN  A
dns2        IN  A
aveproxy    IN  A
2       IN  PTR       dns1.vlab.local.
3       IN  PTR       dns2.vlab.local.
175     IN  PTR       aveproxy.vlab.local.
[aschenck@dns1 ~]$

As you can see, the beginning of these files are the same, but now we introduce PTR (pointer) records. PTR records do the bulk of work when it comes to reverse DNS lookups.

With our zone files created, we can now enable and start the DNS service on CentOS, as well as poking the appropriate hole through the firewall.

systemctl enable named
systemctl start named
firewall-cmd --permanent --add-port=53/tcp
firewall-cmd --permanent --add-port=53/udp
firewall-cmd --reload

Just a few more things to do… change the group of /var/named to named, change the owner and group of /etc/named.conf, and tell SELinux about the new defaults for /var/named as well as /etc/named.conf.

chgrp named -R /var/named
chown -v root:named /etc/named.conf
restorecon -rv /var/named
restorecon /etc/named.conf

The last thing you need to do, assuming all is well, is go back into nmtui and change your DNS IP to your DNS server’s static ip address!

Now, the moment of truth… let’s test our DNS server using dig.

[aschenck@dns1 ~]$ dig

; <<>> DiG 9.9.4-RedHat-9.9.4-29.el7_2.1 <<>>
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 58864
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 4, ADDITIONAL: 5

; EDNS: version: 0, flags:; udp: 4096
;                    IN      A

;; ANSWER SECTION:             300     IN      A

;; AUTHORITY SECTION:             148671  IN      NS             148671  IN      NS             148671  IN      NS             148671  IN      NS

;; ADDITIONAL SECTION:         148671  IN      A         148671  IN      A         148671  IN      A         148671  IN      A

;; Query time: 260 msec
;; WHEN: Mon Dec 21 18:37:13 EST 2015
;; MSG SIZE  rcvd: 191

[aschenck@dns1 ~]$

If you get similar output to what you see above, and your “SERVER” output is your DNS server’s IP address, you’re all set and you can start using your DNS server to resolve names on your lab’s network.

Now that DNS is up and running, I have been able to install the Avamar image proxy on my machine without any problems 🙂 We’ll go over Avamar in a future post.


Things learned today: take the time to set up basic services like DNS as opposed to relying on your consumer router to do it for you. It’s a lot less frustrating to get it set up correctly and then have a dedicated VM to serve your lab than it is to fight with a router that’s marketed towards people who would have zero clue what a pointer record or zone file is!


A little prep goes a long way: thoughts on basic services for a home lab


Image credit:

What’s the saying? “If you find yourself in a hole, the first step is to stop digging.” Sage advice, assuming you follow it, and I’m guilty of not following my own advice.

As I continue to build my lab up, I am finding it increasingly difficult to scale. I am already up to nine VMs and it’s becoming a challenge to manage all of the different DNS names and IPs. Part of the problem is that my router, an ASUS RT-AC68U, is acting as both a DNS and a DHCP server for everything, lab and home network included. While it has worked very well for me as a standard home router and has provided excellent 802.11ac coverage, it is not really well equipped to do things like record editing and manual forward/reverse lookup changes.

In the back of my mind, I knew that this problem was a ticking time bomb. Sooner or later, the inability for me to edit DNS settings before creating it was going to rear its ugly head, and sure enough, today was the day it decided to do so.

I managed to successfully install EMC Avamar Virtual Edition on my lab (hooray! also, I’ll post about this soon!) and I am preparing to do image-level, proxy-driven backups of a couple of VMs. The problem that I am encountering, however, is that Avamar isn’t recognizing the DNS names of the proxy that I am attempting to create as there are no A records to reference, and it won’t let me fix the problem after installation as it will just uninstall the proxy at the first sign of trouble. Clearly, this just won’t do.

The short-term fix, which I will be working on deploying soon, is to deploy a system that acts as a DNS server for my lab. Thankfully I have a ton of different options to do this.

  1. Linux is an obvious choice. DNS is not exactly a high-stress service that requires a lot of power, so it may make sense to deploy a standard CentOS 7 server from a template, load up the dns server, and point all new lab clients to that server for future use. has an excellent writeup on the matter.
  2. There’s another, perhaps more interesting option: pfSense. pfSense is a FreeBSD-based open source firewall/router that a lot of home labbers like to throw around as a good services OS. Again, this would be a low-impact VM, and I don’t mind using something outside of Linux if it makes sense and is purpose-built.

I’ll likely deploy this either tomorrow or over the weekend, but for now, here are my thoughts for future lab builds to make life a little easier:

  1. Start with a plan. It doesn’t have to be a great plan and it can just be a sheet of notebook paper that you quickly sketched out, but don’t just deploy ESXi, throw VMs on top of it, and hope for the best. Have some sort of hierarchy. Will you be using a separate subnet outside of your home network? Will you be deploying VLANs? What will you do for separate physical devices, such as routers, hosts, etc.?
  2. Use Excel or Google Docs to keep track of your VM name, DNS name, IP settings, and so forth. Again, this doesn’t need to be fancy, but you’ll thank yourself down the line. It’ll make troubleshooting and merely expanding your lab so much easier in the future.
  3. If you have access to Visio, use that to diagram your lab as it grows. A visual representation of your lab will go hand in hand with your spreadsheet in both troubleshooting and expanding.
  4. If your lab is going to grow beyond a few VMs (and environments like mine are pretty much guaranteed to do so!), spend time deploying service VMs. DHCP and DNS should absolutely be part of this, and if you are planning on doing anything with Active Directory, plan on doing that as well.
    1. By extension, that means you should also plan on deploying app servers such as SQL as well, if you forsee the need for them!


For my next post, I’ll spend a little time on deploying pfSense and reviewing DNS, and then we’ll talk about Avamar Virtual Edition and why it’s absolutely awesome.



A horrible but functional way to shut down a home lab for the evening


Warning: the following barf– er, bash script might make you ill.

Over the last couple of days I’ve been trying to figure out ways to improve my home lab experience, including automating the tedious shutdown procedure. Most ESXi environments are 24/7, but of course with a home lab there is typically no such need. The trick is to power off the guests gracefully with minimal effort. Enter: scripting!

I currently have five VMs deployed in my lab: two are powered off, one is an embedded ESXi host (that currently runs zero guests), one is a vCenter Server Appliance, and one is the vSphere Management Assistant. The vMA is where all the scripting magic occurs.

The script that I have come up with is admittedly very bad.

# Shutdown script for home lab
#set -x

OUTPUT=( $(esxcli --sessionfile ~/tali01-session vm process list | grep "/vmfs" | cut -c17-256) )

while read -r line; do
    OUTPUTARR=("${OUTPUTARR[@]}" "$line")
done <<< "$OUTPUT"

while true; do
    read -p "Are you sure you want to shut down the lab (Y/N)? " yn
    case $yn in
        [Yy]* )
            echo "Shutting down vSphere lab..."
            for ((i = 0; i < ${#OUTPUTARR[@]}; i++))
                echo ${OUTPUTARR[$i]}
                vmware-cmd --sessionfile ~/tali01-session ${OUTPUTARR[$i]} getstate
                vmware-cmd --sessionfile ~/tali01-session ${OUTPUTARR[$i]} stop soft
                vmware-cmd --sessionfile ~/tali01-session ${OUTPUTARR[$i]} getstate
                sleep 60
            done; exit;;
        [Nn]* )
            echo "Exiting."
        * ) echo "Please answer yes or no.";;

What the script does is this: it invokes the special IFS variable in bash so that it doesn’t choke on whitespace, then it run grabs the output of esxcli. This is where it starts getting awful. –sessionfile is something you can use to authenticate to an ESXi host without having to repeatedly type in a username and password. Here’s the problem: it expires if you don’t use the file within 30 minutes. Already we encounter problem one: you have to generate a new sessionfile every time you want to use this script by way of using –savesessionfile.

Problem number two immediately follows. We’re grepping for config files that we can use in order to power down VMs. I use cut in order to choose the exact part of the string that I want to follow. This is a horrendous way of grabbing a part of a string, because if the output ever changes in how esxcli vm process list works, you’ll get an erroneous cut back. Furthermore, notice that I cut up to character 256… what if our vmx file goes well beyond that by even a single character?

Up next: reading a multi-line output into an array. I banged my head against this part for the last two days. It should be so simple, and ultimately it was a modification of the ubiquitous “x = x + 1” or “x++” method. Take an empty but initialized array, add a single read line, and append it to the array. Repeat until done.

Next up: the actual shutdown. Prompt the user to make he or she actually wants to shut down the lab. If affirmative, start walking through each config file stored in the array and softly power off the guest, waiting 60 seconds before looping back to the beginning. Repeat for each system.

That’s it. The concept is simple enough but there are a few other reasons why the script sucks, such as the fact that it shuts down the very guest it exists on, and there’s no intelligence behind what it shuts down first; it so happens to collect the config files in the order that I want them to shut down but that is horribly hacky and not scalable whatsoever.

I had a good friend of mine (whom is a bazillion times the programmer that I am) look the script over and said that “you told bash to stop being bash”. I thought it was funny.

So, where do we go from here?

  1. Figure out a way to prioritize the shutdown of certain VMs. I have barely scratched the surface of the commands available on vMA, so there’s got to be a way to tag or otherwise identify VMs for position in a shutdown list.
  2. Port this to PowerCLI or figure out some way to make it so that the very VM it runs on isn’t shut down when executing the script.
  3. Come up with options, such as “fast” shutdown where the sleep time is 30 seconds or less, “hard” shutdown where we want everything to go down as quickly as possible (ie yank the power cord), and so on.
  4. The authentication method with the ESXi server is downright miserable. Use something like –credstore instead to make the authentication persistent.

If you have any suggestions that focus on either features or scripting, let me know!


esxcli troubles – order matters!

As part of my efforts to renew my VCP5-DCV certification to the new and shiny VCP6-DCV (not to mention avoiding having to take another week-long class in order to qualify to do so), I have been spinning up a lab environment to mess around with. Like when I was studying for VCP5-DCV, I am using Mastering VMware vSphere 6 by Nick Marshall as my go-to guide.

In my lab, I deployed an instance of the vSphere Management Assistant (vMA) so that I can run vSphere CLI commands such as esxcli. The deployment of vMA went without any problems, but I was having a bunch of trouble getting it to authenticate with vCenter.

esxcli –server= –vihost= -username=administrator@vlab.local network ip interface list

(It may whine about not having a certificate in the credential store… if so, add the certificate.

/usr/lib/vmware-vcli/apps/general/ add -s -t [certificate])

Then I started getting a weird authentication error…


That’s weird. I tried the same password multiple times just to make sure I wasn’t typing it in wrong. No dice. I started looking online and found this thread:

Basically, this guy’s fix was to disconnect the host and reconnect it in vCenter. I tried that. It still failed.

Finally, I found the answer.

After installation, run ESXCLI commands against a specific host by first specifying all dispatcher options. If the target server is a vCenter Server system, specify the target ESXi host before any ESXCLI namespaces, commands, and supported options.

It was purely a matter of what options in the command come first. I ran the command again like this:



Tada! Order DOES matter to esxcli. The book example will not work as formatted.

Up next: scripting the nightly shutdown of the lab.



IT Pilot cleared for takeoff, runway 5



Well, here we are.

I haven’t had a domain name registered in a while but as I start getting serious about becoming an active member in my region’s IT scene, I figure it’s time to commit to a blog.

Here’s a little about me: I am a presales engineer for a large global corporation, covering a variety of established (named) accounts and territory accounts. I focus primarily on backup and recovery hardware and software, and over the last few years I have developed an itch for virtualization, namely vSphere.

I’m a big proponent of solid backup and disaster recovery in both the enterprise as well as at home, and it’s my mission to show both organizations as well as end users the value of a properly maintained backup paradigm.

There are several purposes to this blog; posting my personal thoughts regarding backup and recovery is only one of them. I hold a current VCP certification, of which I am working towards renewing, and my colleague Jonathan Frappier convinced me that I should document my steps towards recertification via blogging. Not a bad idea… I get to discuss my steps, get feedback, learn from others, and contribute back to the community.

You’ll also see other things, like my flying hobby (the title picture should be a tip-off).

So, that’s it for now. Backups, DR, virtualization, and flying. IT Pilot has begun!