Understanding DNS—anatomy of a BIND zone file (2024)

home aaaa ::1 —

Need a clear, thorough guide to understanding how DNS records work? We got you.

Jim Salter -

Understanding DNS—anatomy of a BIND zone file (1)

If you want to be a sysadmin or network administrator of any kind, there's a fundamental technology you really need to understand—DNS, the Domain Name System. There was a time when a sysadmin with no aspirations to managing Internet-accessible services might have gotten by without understanding DNS, but that time is long, long gone.

You can't learn everything there is to know about DNS in a single article. But that's not what we're looking to do today; instead, we want to give you a clear, concise guide to the structure and meaning of the most important part of the Domain Name System: a zone file, as seen in BIND, the Berkeley Internet Name Daemon.

Sample zone file

Understanding DNS—anatomy of a BIND zone file (2)

Origin and TTL

Above, we have a small but complete example of a typical zone file—in fact, it's an anonymized version of a production zone file on a domain I manage. Let's go through it line by line.

$ORIGIN tld.$TTL 5m

Whenever you see an $ORIGINline in a zone file, this is a shortcut that lets BIND know that any unterminated hostname references following that line should be presumed to end in the argument following $ORIGIN. In this case, that's .tld—the fictional Top Level Domain for example.tld.

The next line, $TTL 5m, declares that following lines will have a Time To Live of five minutes. This relatively short value means that remote DNS resolvers should only cache records retrieved from this zone for five minutes before requesting them again. If you're relatively certain that your DNS for a given domain won't change very often, you might consider increasing that value in order to reduce the number of times remote hosts must query your nameserver—but keep in mind that a longer TTL also means longer periods of downtime, when you must make a change to your DNS (or make a change that accidentally breaks it).

Both $ORIGINand $TTLcan be defined multiple times in the same zone—each time you redefine them, you change their value for any lines beneath the new values in the same zone file.

SOA record

example IN SOA ns1.example.tld. hostmaster.example.tld. ( 90 ; serial 4h ; refresh 15m ; retry 8h ; expire 4m) ; negative caching TTL

The first actual record in our sample zone file—or in any normal zone file—is the SOA record, which tells us the Start Of Authority for the domain. It's also easily the most confusing record type in the entire DNS system.

For any record listing, including this SOA record, the first argument is the hostname the record applies to—in this case, example. Remember how we set $ORIGIN tldon the first line of the zone file? That means that this unterminated hostnameexampleexpands to example.tld—so, we're defining the SOA for the FQDN (fully qualified domain name) example.tld.

We're referring to this hostnameexampleas "unterminated" because it doesn't end in a dot. If we wanted to bypass the $ORIGINsetting and refer to a FQDN directly, we'd terminate it with a final dot—eg, example.tld.would be the FQDN here,with the trailing dot.

The next argument we see is IN, short for "Internet." This is the record class. There are other DNS record classes, but you can easily go your entire career without seeing one of them (such as CH, for Chaos) in production. The record class is optional; if omitted, BIND will assume that the record being specified is of class IN. We recommendnot omitting it, however, lest something change and all your zone files suddenly be broken after a BIND update!

The next two arguments are FQDNs—at least, they look like it. The first FQDN really is an FQDN, and it should be the FQDN of the primary name server for the domain itself—in this case, ns1.example.tld.Note that youcan use unterminated hostnames here—for example, we could have just used ns1.examplefor this argument, which would have expanded to ns1.example.tld.thanks to our $ORIGIN .tldline—but it's probably best to be explicit here.

The second FQDN, hostmaster.example.tld., isn't actually an FQDN at all. Instead, it's a perverse way of rewriting an email address. @is a reserved character in zone files, and the original BIND uses the first section of this "FQDN" as the user portion of an email address—so, this would translate to the address hostmaster@example.tld. It'sincredibly common to see this screwed up in real-life zone files—thankfully, it doesn't much matter. We're not aware of literally anyone who actually uses this feature of a DNS zone to contact anyone.

Moving on, we have serial, refresh, retry, expire, and negative TTLfor the zone inside parentheses. Note that the comments you see here labeling them are not required—and in real life, you'll rarely see them. We strongly prefer to put these comments in production zone files in order to make it easier to read them, but BIND itself doesn't care!

  • serial—this is a simple serial number for the zone file, which must be incremented each time the contents of the zone are changed. If you don't update the zone file serial, your changes to the zone will not be picked up by DNS resolvers that have previously cached records from your zone! This used to be a YYMMDDnn format in days gone by—but that format is no longer required, or in some cases even supported. Just start your zones with serial 1, increment to 2the next time you make a change to the zone, and so forth.
  • refresh—after this period of time, secondary nameservers should query the primary nameserver for this SOA record, to detect changes in serial number. If the serial number has incremented, any cached records must be invalidated and fetched again from the primary nameserver.
  • retry—if the primary nameserver doesn't respond to an SOA request, a secondary nameserver should wait this long before attempting to query the primary nameserver again.
  • expire—if the primary nameserver has failed to respond to a secondary nameserver's SOA request for this period of time, the secondary nameserver should stop offering DNS resolution for the domain entirely.
  • negative caching TTL—this controls how long a "negative" response—eg, "I don't have the record you're asking for"—should be cached.

One of the most common areas for confusion in the SOA record is what effect therefresh, retry, and expirearguments have. These arguments don't affect DNS resolvers at all—only secondary authoritative nameservers for the domain. if you don't have one or more secondary nameservers for your domain, which use BIND replication to retrieve updates from the primary, these arguments won't have any effect at all.

One final note: older versions of BIND required all of these times to be in seconds... even when the actual time interval was in days, or weeks. BIND9—released almost 20 years ago, in October 2000—supports human-readable time sufffixes such as "m" for minutes, "h" for hours, and "d" for days.Please use these human readable suffixes when writing zone files; nobody should have to break out a calculator to figure out that 86,400 seconds is one day!

NS records

IN NS ns1.example.tld.IN NS ns2.example.tld.

In these two records, we define the hostnames, which are authoritative nameservers for our zone. Once again, we've used dot-terminated FQDNs for these records. Once again, wecould have used unterminated hostnames—ns1.exampleand ns2.example—and relied on our $ORIGIN .tldto expand them. Doing so would make the zone more confusing and difficult to read, though.

Note that the NS record specifieshostnames, not IP addresses. This is a common source of confusion for DNS newbies, and it's important to get it right. Youcannot specify a bare IP address as the nameserver for a domain; you absolutely must specify a hostname here.

Finally, note that we haven't specified the domain name itself on either line—this is because we've inherited it from the SOArecord above. We started that line with example, which expands to example.tld. Since we haven't specified another hostname, these new NSrecords also apply to that hostname by default.

In the real world, you may also see zone files with $ORIGIN example.tld., and beginning the SOA and possibly other lines with the special reserved character @. When you see @as a hostname in a zone file, that just means you're using the bare $ORIGINwithout any further qualifiers.

MX record(s)

IN MX 10 mail.example.tld.

In this simple domain, we have a single mailserver, and it's mail.example.tld.The MX record just tells anyone who wants to send email to any address at example.tldto make their SMTP connection to the hostname specified in this record.

The preceding argument—10in this case—is the numeric priority of the mailserver in this specific record. Lower numbers mean higher priority. When multiple SMTP servers are available for a domain, you'll see multiple MXrecords as well, each with a different priority. In theory, higher priority mailservers should always be tried first, and lower priority mailservers only tried if the higher priority server fails.

Well-behaved SMTP servers do follow this protocol—but spammers have a tendency to deliberately target the lower-priority mailservers first, operating on the theory that high-priority servers might be anti-spam gateways, and the lowest priority servers might be the bare, unfiltered end server. Spammers suck.

A record(s)

IN A 127.0.0.1

A records are the part of a zone file that actually do what most people think of DNS as doing—they translate a hostname to a bare IPv4 address. In this case, this is a sample file only—and our Arecord for example.tldmerely resolves to localhost, on the same principle that phone numbers in movies always start with the exchange 555. In real life, of course, you'd put in the IP address of the server you expected to answer when you ping example.tld, point a Web browser to https://example.tld/, and so forth.

In this simple zone file, we only have a single Arecord for example.tld. In real life, you might encounter several—there could be multiple gateway servers capable of answering Web requests for https://example.tld/; and if so, each would get their own A record on their own line.

TXT record(s)

IN TXT "v=spf1 a mx a:mail.example.tld a:www.example.tld ?all"

This TXT, or text record, is still in the head section of our zone file, under the hostname example.tld. So its scope is the entire example.tlddomain. You can put just about anything in a TXTrecord; this specific one is an SPFrecord, formatted to give mailservers information about what machines are authorized to emit mail on behalf of example.tld.

In this case, we're saying that we're using the SPF1 version of formatting. We then inform anyone querying this record that any valid A record for example.tldis authorized to send mail on its behalf, as is any validMXfor the domain, and finally that the IP addresses associated with the Arecords for mail.example.tldand www.example.tldare authorized to send mail. Finally, ?allsays that if any other machine says it wants to send mail from some address at example.tld, it should be allowed... but it should be examined more closely than specifically authorized hosts are.

Hostnames, subdomains, and CNAMEs beneath example.tld

$ORIGIN example.tld.ns1 IN A 127.0.0.2ns2 IN A 127.0.0.3www IN CNAME example.tld.mail IN AAAA ::1mail IN A 127.0.0.4

Now that we've defined everything we need to for the domain, we can start adding records for any hostnames and subdomainsbeneathexample.tlditself. The first thing we do here is change our $ORIGINto example.tld.Again, notice that final terminating dot—if you forget it, things are going to get really strange and you'll tear your hair out wondering why none of your records resolve properly!

We see Arecords here for ns1, ns2, andmail. These Arecords work the same way that theArecord for the domain itself did—we are telling BIND what IP address to resolve requests for that hostname to.

We also have an AAAArecord for mail.example.tld.AAAArecords are just like Arecords, but they're for resolving IPv6 rather than IPv4. Once again, we've chosen in our example to use a localhost address. You'll need to be familiar with AAAArecords if you expect to set up your own mailserver—Google stopped being willing to talk to mailservers without fully working IPv6 DNS a few years ago!

The last record type we see here is CNAME, short for Canonical Name. This is an alias—it allows you to tell BIND to always resolve requests for the CNAMEd host using the A or AAAA record specified in the target argument. In this case, www IN CNAME example.tld.means that the IP address for example.tlditself should also be handed out if somebody asks for www.example.tld.

CNAMErecords are handy, but they're a bit funky. It's worth remembering that each level of CNAMEnecessitates another DNS lookup—in this case, a remote machine that asked to resolve www.example.tldwould be told "please look up example.tld.in order to find your answer," and then would need to issue aseparate DNS request for the Arecord associated with example.tld.If you have CNAMEs pointing to CNAMEs pointing to CNAMEs, you'll introduce unnecessary latency into requests for your resources, and your domain will appear "slow" and "laggy" to your users!

There are further limitations in CNAMErecords. Remember how we told you thatMXand NSrecords must point to hostnames, not to raw IP addresses? More specifically, they must point directly to Arecords, not to CNAMErecords. If you try to set MX mail.example.tld.followed by mail.example.tld. CNAME example.tld., your zone file will be broken, and MXlookup attempts will return errors.

Tools of the trade

If you're managing your own DNS, you'll need to be proficient in using command line tools to query your DNS server directly and see how it responds to requests—it's difficult to be certain whether the problem is DNS or something else just by putting https://example.tld/in a browser and seeing what happens.

dig

you@box:~$ dig @127.0.0.1 NS example.tld; <<>> DiG 9.16.1-Ubuntu <<>> NS example.tld;; global options: +cmd;; Got answer:;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 51417;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 1, ADDITIONAL: 1;; OPT PSEUDOSECTION:; EDNS: version: 0, flags:; udp: 65494;; QUESTION SECTION:;example.tld.INNS;; ANSWER SECTION:example.tld.300INNSns1.example.tld.example.tld.300INNSns2.example.tld.;; Query time: 40 msec;; SERVER: 127.0.0.1(127.0.0.1);; WHEN: Sat Aug 22 00:54:26 EDT 2020;; MSG SIZE rcvd: 74

If you have access to Linux, Mac, or Windows Subsystem for Linux, by far the best command line tool is dig. Using digis as simple as specifying a server to query, the record type you want to look for, and the FQDN it should be associated with.

In the example above, we asked the DNS server at 127.0.0.1to show us all NSrecords associated with example.tld. In addition to the answers we wanted, we got a ton of diagnostic information—the DNS server we queried did not return an ERRORwhen queried, it says it is authoritative for the domain in question, and so forth.

You can also supply a +shortargument if you want digto just shut up and give you the answer you're looking for without all the verbose diagnostics:

you@box:~$ dig +short @127.0.0.1 NS example.tldns1.example.tld.ns2.example.tld.

Be aware, though, that if there aren't any answers available for a +short query—for example, if you typo the domain name—you won't get any response at all, even if the DNS server queried returned an error.

you@box:~$ dig +short @127.0.0.1 NS example.tmdyou@box:~$

If you want to find outwhy you didn't get an answer, you'll need to lose the +shortargument to find out.

nslookup

If you don't have access to dig, you can generally get by with nslookup. Most commonly, this is a semi-cursed workaround for users sitting at a Windows box without access to Windows Subsystem for Linux, cygwin, or some other way to gain access to more advanced tools than the Windows CLI provides.

nslookupis usually invoked without arguments and queried in interactive mode. Here's a sample session:

C:\> nslookup> server 127.0.0.1Default server: 127.0.0.1Address: 127.0.0.1#53> example.tldServer: 127.0.0.1Address: 127.0.0.1#53Non-authoritative answer:Name: example.tldAddress: 127.0.0.1

By setting server 127.0.0.1, we specified to nslookupto use that machine as the DNS server to query. You don't have to specify this; if you don't, nslookupwill use whatever the default DNS resolver on your machine would.

After optionally setting the server, you can just type a bare hostname into nslookup's interactive prompt, and it will return any Aor AAAArecords it can find for that hostname.

If you want to query the remote server for a different type of record, you'll need to use a set typecommand.

> set type=ns> example.tldServer: 127.0.0.1Address: 127.0.0.1#53Non-authoritative answer:example.tld nameserver = ns1.example.tld.example.tld nameserver = ns2.example.tld.Authoritative answers can be found from:> set type=mx > example.tldServer: 127.0.0.1Address: 127.0.0.1#53Non-authoritative answer:example.tld mail exchanger = 10 mail.example.tld.Authoritative answers can be found from:example.tld nameserver = ns2.example.tld.example.tld nameserver = ns1.example.tld.mail.example.tld internet address = 127.0.0.4> exit

In the above examples, we used set type=nsand set type=mxto query the remote DNS server for NSand MXrecords for example.tld. It works, and you get your answers... but the syntax is fiddly, there's less diagnostic information available, it's vastly less scriptable, and if you're anything like us, you'll likely curse the antiquated thing once or twice before you're done.

The proper way to get out of nslookup's interactive mode is the command exit. Hopefully, you never need to look up information about a top-level domain also named exit—or if you do, you'll have a better tool available than nslookupwhen you do.

Conclusions

Hopefully, you picked up something valuable today about how DNS works and how its information is stored. Although BIND is not the only DNS server platform out there—in particular, Windows admins will need to work with Active Directory DNS—the lessons learned here apply near-equally to all platforms and applications.

Although the storage format may change somewhat from server to server—such as an Active Directory domain controller literally storing zones inside Active Directory itself, rather than a plain text file—the record types are universal, and the formatting at least near-universal.

If you're a budding sysadmin or enthusiast who's interested in running your own DNS server, I highly recommend doing it—and using the original platform when you do; BIND on either Linux or BSD. The system load of running a nameserver is nearly nonexistent at any scale short of truly massive; a $5 Digital Ocean or Linode box can handle the job just fine.

In addition to the sheer joy of learning how to manage these things, you may also find you value the ability to set your TTLs absurdly short—most managed DNS servers won't allow a TTL of less than 30m, and most will attempt to default you to TTLs of up to a week. This is fine and dandy for a DNS zone, which is already properly set up and doesn't need changing... but if your IP address changes and your DNS needs to change along with it, a five-minute TTL is a very, very fine thing to have.

Understanding DNS—anatomy of a BIND zone file (2024)

FAQs

What does a DNS zone file contain? ›

A zone file is a plain text file stored in a DNS server that contains an actual representation of the zone and contains all the records for every domain within the zone.

What is a BIND zone file? ›

A Domain Name System (DNS) zone file is a text file that describes a DNS zone. The BIND zone file is a file format that has been widely adopted by DNS server software. The format is defined in RFC 1035.

How do DNS zones work? ›

A DNS zone is a distinct part of the domain namespace which is delegated to a legal entity—a person, organization or company, who are responsible for maintaining the DNS zone. A DNS zone is also an administrative function, allowing for granular control of DNS components, such as authoritative name servers.

What are the 3 types of DNS zones? ›

Types of DNS Zones
  • Primary zone.
  • Secondary zone.
  • Active Directory-integrated zone.
  • Stub zone.
  • Reverse lookup zone.
May 10, 2021

How DNS works step by step? ›

How Does the DNS Process Work?
  1. Step 1: Requesting Website Information.
  2. Step 2: Contact the Recursive DNS Servers.
  3. Step 3: Query the Authoritative DNS Servers.
  4. Step 4: Access the DNS Record.
  5. Step 5: Final DNS Step.
  6. Authoritative DNS Server.
  7. Recursive Nameserver.
Sep 1, 2020

Where are BIND zone files stored? ›

The BIND nameserver named server uses the /etc/named. conf file for configuration. All zone files are placed in the /var/named/ directory.

What is $origin in zone file? ›

$ORIGIN is used in two contexts during zone file processing: The symbol @ forces substitution of the current (or synthesized) value of $ORIGIN. The @ symbol is replaced with the current value of $ORIGIN. The current value of $ORIGIN is added to any 'unqualified' name (any name which does not end in a 'dot').

How do you comment in a zone file? ›

Comments start with a semicolon ";" and go to the end of line. Empty lines are allowed; any combination of tabs and spaces acts as a delimiter.

How do I create a DNS zone file? ›

  1. Open the Server Manager.
  2. Click DNS.
  3. Right-Click on your server and then click DNS Manager.
  4. Inside of DNS Manager... Expand your server. Expand Forward Lookup Zones. Right-Click on your Zone(Domain Name) and choose the type of record you want to create. NOTES:
Sep 17, 2012

How do DNS zones and records interact with each other? ›

A DNS zone is used to host the DNS records for a particular domain. To start hosting your domain in Azure DNS, you need to create a DNS zone for that domain name. Each DNS record for your domain is then created inside this DNS zone.

What is the difference between a zone and a domain in DNS? ›

A domain is a logical division of the DNS name space whereas a zone is physical, as the information is stored in a file called a zone file. In most cases you have a 1 to 1 relationship between a Domain and a DNS Zone i.e. the domain mydomain.com would be stored in a zone file called mydomain.com.

What is the stub zone in DNS? ›

A stub zone is a copy of a Domain Name System (DNS) zone that contains only resource records that identify the DNS servers for that zone. You can add either a forward lookup zone or a reverse lookup zone. You can add either an Active Directory-integrated zone or a file-backed zone.

What is primary secondary and stub zone? ›

Types of DNS Zones

In the original implementation of DNS found in RFCs 1034 and 1035, two different types of zones were defined: Primary zones, which store their zone information in a writable text file on the name server. Secondary zones, which store their zone information in a read-only text file on the name server.

What is DNS primary and secondary zones? ›

Primary (Master) DNS zone – holder of the original zone file (all the DNS records for the zone). You can manage a host through this zone. Secondary (Slave) DNS zone – holds a copy of the zone file. You can use them for better performance, for hiding your Primary, for backup and redundancy.

How many lookup zones are in DNS? ›

There are two main categories of lookup zones: forward lookup zones and reverse lookup zones. Forward lookup zones are used to map a host name to an IP address.

Top Articles
Latest Posts
Article information

Author: Velia Krajcik

Last Updated:

Views: 6163

Rating: 4.3 / 5 (74 voted)

Reviews: 81% of readers found this page helpful

Author information

Name: Velia Krajcik

Birthday: 1996-07-27

Address: 520 Balistreri Mount, South Armand, OR 60528

Phone: +466880739437

Job: Future Retail Associate

Hobby: Polo, Scouting, Worldbuilding, Cosplaying, Photography, Rowing, Nordic skating

Introduction: My name is Velia Krajcik, I am a handsome, clean, lucky, gleaming, magnificent, proud, glorious person who loves writing and wants to share my knowledge and understanding with you.