Chapter 4. Managing Zone Data
With traditional DNS servers, such as BIND, administrators usually manage primary zone data as files. More recently, DNS servers have begun to support loading primary zone data from other sources, such as databases.
CoreDNS supports a variety of methods to manage zone data. Some will be very familiar to DNS administrators, like zone data files; others are more modern, such as using Git; whereas some are downright retro (host tables, anyone?). In this chapter, we cover all of them.
Together, these options provide administrators with flexibility and, in some cases, advanced functionality in the mechanism they use to manage zone data. Host tables, for example, provide a simple way to add name-to-address and address-to-name mappings without the overhead of creating and maintaining an entire zone data file. Git, on the other hand, provides distributed version-control capabilities.
Let’s begin with the file
plug-in, which supports zone data files. We actually covered this in Chapter 3, but we go through it in more detail here.
The file Plug-in
For an administrator with experience managing zone data files, the file
plug-in is probably the most familiar mechanism CoreDNS offers. file
configures CoreDNS as the primary DNS server for one or more zones. In its simplest form, the file
plug-in takes the syntax shown in Example 4-1.
Example 4-1. Simple file plug-in syntax
file DBFILE [ZONES...]
DBFILE
is a zone data file containing resource records. You can specify DBFILE
as a full pathname or as a relative pathname; relative pathnames are interpreted relative to any path set with the root
directive.
ZONES
is an optional list of one or more zones described by the resource records in DBFILE
. If ZONES
is omitted, CoreDNS uses the zones from the configuration block.
Example 4-2 presents a simple example of a file
plug-in, and Example 4-3 shows the zone data file it refers to.
Example 4-2. Simple example of a file plug-in
foo.example { file db.foo.example }
Example 4-3. db.foo.example
@ 3600 IN SOA ns1.foo.example. root.foo.example. ( 2019041900 3600 600 604800 600 ) 3600 IN NS ns1.foo.example. 3600 IN NS ns2.foo.example. ns1 IN A 10.0.0.53 IN AAAA 2001:db8:42:1::53 ns2 IN A 10.0.1.53 IN AAAA 2001:db8:42:2::53 www IN A 10.0.0.1 IN AAAA 2001:db8:42:1:1
Because the resource records in the db.foo.example
zone data file are all attached to relative domain names (e.g., ns1
and www
rather than dot-terminated fully qualified domain names), the file can be loaded to describe multiple zones, as shown in Example 4-4.
Example 4-4. Using a single zone data file for multiple zones
. { file db.foo.example foo.example bar.example }
This assumes that you want the contents of foo.example and bar.example to be identical, of course—for example, that you want both www.foo.example and www.bar.example to map to the IPv4 address 10.0.0.1.
The file
plug-in also supports a more extensive syntax that allows you to specify which DNS servers are allowed to transfer the zone(s) and how frequently to check the zone data file for changes, as demonstrated in Example 4-5.
Example 4-5. More detailed syntax of the file plug-in
file DBFILE [ZONES... ] { transfer to ADDRESS... reload DURATION upstream [ADDRESS...] }
Without a transfer
directive, CoreDNS will not allow zone transfers of the zone or zones described by the file
plug-in. To send NOTIFY messages to a particular secondary DNS server as well as to allow zone transfers to that secondary, specify the secondary’s IP address. For multiple secondaries, you can list their IP addresses in a single transfer
directive or use multiple directives. You can also specify a network in Classless Inter-Domain Routing (CIDR) notation to allow zone transfers from any IP address on that network, or *
to allow zone transfers from anywhere, as presented in Example 4-6.
Example 4-6. Detailed example of the file plug-in
foo.example { file db.foo.example { transfer to 10.0.1.53 transfer to * } }
reload
allows you to specify how frequently CoreDNS checks the zone data file to determine whether the serial number in the start of authority (SOA) record has changed. When CoreDNS detects a new serial number, it reloads the file (as one or more zones) and sends NOTIFY messages to secondary DNS servers designated in transfer
directives. The default reload
is one minute; a setting of 0
disables the periodic check. Valid values are a number followed by “s” for seconds, “m” for minutes, and “h” for hours; for example, 30s
for 30 seconds.
The file
plug-in is fine if you’re configuring CoreDNS as the primary DNS server for a few zones. But what if you want CoreDNS to be primary for hundreds of zones? In that case, you want the auto
plug-in.
The auto Plug-in
The auto
plug-in provides a clever way to load a large number of zones from multiple zone data files at once. This minimizes the length and complexity of the Corefile and provides the ability to automatically configure CoreDNS as the primary for new zones. Example 4-7 shows the syntax.
Example 4-7. Syntax of auto plug-in
auto [ZONES...] { directory DIR [REGEXP ORIGIN_TEMPLATE] transfer to ADDRESS... reload DURATION }
auto
tells CoreDNS to scan the directory for files matching the pattern db.*
. Each file is interpreted as a zone data file whose origin is what follows db.
. That origin must be within the zone or zones listed in ZONES
, if specified.
Suppose that the directory /etc/coredns/zones contains the zone data files db.foo.example and db.bar.example, which describe the zones foo.example and bar.example, respectively. The auto
plug-in shown in Example 4-8 would instruct CoreDNS to read the entire directory and load the foo.example and bar.example zones from those files.
Example 4-8. An auto plug-in
auto example { directory /etc/coredns/zones }
Moreover, you can create another zone (under the example domain, anyway) just by creating a new, appropriately named zone data file in /etc/coredns/zones.
You can also specify a regular expression besides db.*
for CoreDNS to look for in the directory, and give CoreDNS instructions on how to create the origin (and domain name of the zone) from the filename. If, for example, you named your zone data files <domain>.zone, you could use the auto
plug-in presented in Example 4-9.
Example 4-9. Another auto plug-in
auto example { directory /etc/coredns/zones (.*)\.zone {1} }
The regular expression (regex) is expected to incorporate what is essentially a Perl capture group: the parentheses around “.*” indicate the portion of the filename that contains the origin (in this case, everything before .zone
); the {1}
is a backreference to that portion of the regex. You can use other backreferences, of course, such as {2}
for the second capture group.
Finally, you can use the file
directives transfer
, reload
, and upstream
to control which DNS servers can perform zone transfers of these zones (and receive NOTIFY messages from CoreDNS), how often the directory is scanned for modified zone data files, and which DNS servers to use to resolve external domain names.
Using the auto Plug-in with Git
Avid users of the Git distributed version-control system can easily combine the auto
plug-in with a script such as git-sync
to periodically pull zone data files from a Git repository into a directory. CoreDNS then scans the directory and loads new and modified zones. Using Git allows multiple administrators to jointly manage a set of version-controlled zone data files so that administrators can track changes to zone data.
git-sync
is, not surprisingly, implemented as a container. Here’s an example of using git-sync
to periodically scan a GitHub repository for new zone data files, as demonstrated in Example 4-10.
Example 4-10. git-sync in action
docker run -d \ -v /etc/coredns/zone:/tmp/git \ registry/git-sync \ --repo=https://github.com/myzonedata --branch=master --wait=30
This command uses the git-sync
container to synchronize files from the https://github.com/myzonedata repository to /etc/coredns/zone and to check the repository every 30 seconds for changes.
What if you have the opposite problem that auto
solves—namely, that you just want to load a few resource records into CoreDNS without the overhead of a zone data file. Well then, the hosts
plug-in will come in handy.
The hosts Plug-in
The hosts
plug-in is used to configure CoreDNS to generate zone data from a host table (e.g., /etc/hosts). The host table must be in the standard host table format:
<IP address> <canonical name> [aliases...]
The IP address can be either an IPv4 or an IPv6 address. The canonical name and any aliases must be domain names. After the host table is read, hosts
generates the following:
- A records for each entry with an IPv4 address, mapping the canonical name and any aliases to the specified IPv4 address
- AAAA records for each entry with an IPv6 address, mapping the canonical name and any aliases to the specified IPv6 address
- A PTR record for either an IPv4 or IPv6 address, mapping the address back to the canonical name
Note that the aliases become A or AAAA records, not canonical name (CNAME) records.
Example 4-11 presents the syntax of the hosts
plug-in.
Example 4-11. Syntax of the hosts plug-in
hosts [FILE [ZONES...]] { [INLINE] ttl SECONDS no_reverse reload DURATION fallthrough [ZONES...] }
FILE
specifies the name of the hosts file to read and parse; by default, CoreDNS reads /etc/hosts. If FILE
is a relative pathname, it’s interpreted relative to the directory specified in the ROOT
directive.
ZONES
is an optional list of one or more zones that are loaded from the host table. If ZONES
isn’t specified, CoreDNS uses the zones from the enclosing server block. Domain names will be loaded only into the zones of which they are a part. In other words, if you load the host table shown in Example 4-12 as both foo.example and bar.example, you’ll end up with host1.foo.example in the foo.example zone and host2.bar.example in bar.example.
Example 4-12. Example host table
10.0.0.1 host1.foo.example 10.0.1.1 host2.bar.example
Zones whose data is read using the hosts
plug-in aren’t really complete zones; they don’t have SOA records, for example, so they can’t be transferred to another DNS server. Consequently, hosts
isn’t usually used for management of an entire zone; rather, you would use it for loading discrete domain names. For example, some people load a host table that includes domain names used in serving ads and that maps those domain names to the IP address 0.0.0.0.
[INLINE]
allows you to specify one or more lines in host table format directly in the directive, as shown in Example 4-13.
Example 4-13. Inline host table entries
foo.example { hosts { 10.0.0.1 host1.foo.example 10.0.1.1 host2.foo.example } }
TTL
sets the time-to-live (TTL) value for records synthesized from host table entries; by default, the TTL is set to 3600 seconds, or 1 hour. The value must be specified as an integer (in other words, don’t specify units such as “s” for seconds).
no_reverse
inhibits the creation of PTR records from host table entries.
By default, CoreDNS reloads the host table every 5 seconds. reload
allows you to change this interval by specifying a scaled value (i.e., a number followed by a unit of time) with the following units:
- ns for nanoseconds
- us or µs for microseconds
- ms for milliseconds
- s for seconds
- m for minutes
- h for hours
I’m not sure you really need the ability to specify a reload interval of 500,000,000 nanoseconds (with 500000000 ns), but with CoreDNS, you can!
Finally, fallthrough
controls whether queries for the zones handled by the hosts
plug-in fall through to another plug-in if no answer is found. For example, you might want queries for foo.example to fall through from the hosts
plug-in to a file
plug-in if the answer wasn’t found in the host table. By default, specifying fallthrough
instructs CoreDNS to fall through for any queries handled by the hosts
plug-in. To fall through only for a subset of those queries, you can specify a list of zones as an argument.
Next, we look at a way to load zone data from Amazon’s Route 53 service.
The route53 plug-in
Many organizations use the Amazon Route 53 service to provide authoritative DNS services from the Amazon Web Services (AWS) cloud. CoreDNS provides a plug-in, route53
, that enables it to synchronize zone data from Route 53, much like a secondary DNS server would transfer zone data from a master DNS server. CoreDNS can then respond authoritatively to queries for domain names in the synchronized zone.
Example 4-14. Syntax of the route53 plug-in
route53 [ZONE:HOSTED_ZONE_ID...] { [aws_access_key AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY] upstream credentials PROFILE [FILENAME] fallthrough [ZONES...] }
To synchronize the zone, CoreDNS must provide the domain name of the zone and a special “Hosted Zone ID” used within AWS as well as credentials that authenticate CoreDNS to Route 53.1 To get the zone ID, log in to the AWS Dashboard, go to the Route 53 service, and then click “Hosted zones.” This should bring up a table of zones that includes each zone’s Hosted Zone ID.
The route53
plug-in requires that you specify the domain name of the zone and the Hosted Zone ID in a particular (and particularly inflexible) format: the domain name of the zone, terminated with a dot, followed by a colon, then the Hosted Zone ID. Example 4-15 demonstrates this format.
Example 4-15. The route53 plug-in
route53 foo.example.:Z3CDX6AOCUSMX3 { fallthrough }
You can specify multiple zones if you want CoreDNS to synchronize all of them from Route 53.
By default, CoreDNS determines the AWS credentials to use from environment variables or an AWS credentials file. You can override this behavior by specifying the credentials directly within the route53
plug-in, as illustrated in Example 4-16.
Example 4-16. route53 plug-in with explicit credentials
route53 foo.example.:Z3CDX6AOCUSMX3 { aws_access_key AKIAIMSX7F33X4MOVBZA SnA4XxFPx/BDEMbty3EKVze7Xi3DkQ5a8akRO9j9 }
You can also specify an AWS credentials file other than the default using the credentials
subdirective shown in Example 4-17.
Example 4-17. route53 plug-in with credentials file
route53 foo.example.:Z3CDX6AOCUSMX3 { credentials default .awscredentials }
default
, in this case, specifies a particular profile in the credentials file.
Like hosts
, the route53
plug-in supports fallthrough
to other plug-ins, for all or a specified set of zones synchronized from Route 53. And, like file
, route53
supports specification of an upstream
DNS server to resolve references to external domain names in the Route 53 zone data.
That’s the last of the plug-ins for managing zone data in CoreDNS. Hopefully, among the four options (five if you count using the auto
plug-in with Git), you’ll find one that meets your needs.
Although CoreDNS is a flexible and capable primary DNS server, its strength, of course, is supporting DNS-based service discovery. We cover that in Chapter 5.
1 The Hosted Zone ID uniquely identifies the zone to AWS. The domain name of the zone alone isn’t always enough, because AWS might have Public Hosted Zones and Private Hosted Zones with the same domain name.
Get Learning CoreDNS now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.