coredns-log

title: coredns-log(7)

text:
# coredns-log(7)

## NAME
log - enables query logging to standard output.

## DESCRIPTION
By just using log you dump all queries (and parts for the reply) on standard output. Options exist to tweak the output a little. Note that for busy servers logging will incur a performance hit.

Enabling or disabling the log plugin only affects the query logging, any other logging from CoreDNS will show up regardless.

## SYNTAX

```
log
```

With no arguments, a query log entry is written to stdout in the common log format for all requests. Or if you want/need slightly more control:

```
log [NAMES...] [FORMAT]
```

- NAMES is the name list to match in order to be logged

- FORMAT is the log format to use (default is Common Log Format), {common} is used as a shortcut for the Common Log Format. You can also use {combined} for a format that adds the query opcode {>opcode} to the Common Log Format.

You can further specify the classes of responses that get logged:

```
log [NAMES...] [FORMAT] {

    class CLASSES...
}
```

•

CLASSES is a space-separated list of classes of responses that should be logged

The classes of responses have the following meaning:

- success: successful response

- denial: either NXDOMAIN or nodata responses (Name exists, type does not). A nodata response sets the return code to NOERROR.

- error: SERVFAIL, NOTIMP, REFUSED, etc. Anything that indicates the remote server is not willing to resolve the request.

- all: the default - nothing is specified. Using of this class means that all messages will be logged whatever we mix together with "all".

If no class is specified, it defaults to all.

## LOG FORMAT
You can specify a custom log format with any placeholder values. Log supports both request and response placeholders.

The following place holders are supported:

- {type}: qtype of the request

- {name}: qname of the request

- {class}: qclass of the request

- {proto}: protocol used (tcp or udp)

- {remote}: client's IP address, for IPv6 addresses these are enclosed in brackets: [::1]

- {local}: server's IP address, for IPv6 addresses these are enclosed in brackets: [::1]

- {size}: request size in bytes

- {port}: client's port

- {duration}: response duration

- {rcode}: response RCODE

- {rsize}: raw (uncompressed), response size (a client may receive a smaller response)

- {>rflags}: response flags, each set flag will be displayed, e.g. "aa, tc". This includes the qr bit as well

- {>bufsize}: the EDNS0 buffer size advertised in the query

- {>do}: is the EDNS0 DO (DNSSEC OK) bit set in the query

- {>id}: query ID

- {>opcode}: query OPCODE

- {common}: the default Common Log Format.

- {combined}: the Common Log Format with the query opcode.

- {/LABEL}: any metadata label is accepted as a place holder if it is enclosed between {/ and }, the place holder will be replaced by the corresponding metadata value or the default value - if label is not defined. See the metadata plugin for more information.

The default Common Log Format is:

```
`{remote}:{port} - {>id} "{type} {class} {name} {proto} {size} {>do} {>bufsize}" {rcode} {>rflags} {rsize} {duration}`
```

Each of these logs will be outputted with log.Infof, so a typical example looks like this:

```
[INFO] [::1]:50759 - 29008 "A IN example.org. udp 41 false 4096" NOERROR qr,rd,ra,ad 68 0.037990251s
~~~~
## Examples
Log all requests to stdout
~~~ corefile
. {

    log

    whoami
}
```

Custom log format, for all zones (.)

```
. {

    log . "{proto} Request: {name} {type} {>id}"
}
```

Only log denials (NXDOMAIN and nodata) for example.org (and below)

```
. {

    log example.org {

        class denial

    }
}
```

Log all queries which were not resolved successfully in the Combined Log Format.

```
. {

    log . {combined} {

        class denial error

    }
}
```

Log all queries on which we did not get errors

```
. {

    log . {

        class denial success

    }
}
```

Also the multiple statements can be OR-ed, for example, we can rewrite the above case as following:

```
. {

    log . {

        class denial

        class success

    }
}
```


coredns-loop

title: coredns-loop(7)

text:
# coredns-loop(7)

## NAME
loop - detects simple forwarding loops and halts the server.

## DESCRIPTION
The loop plugin will send a random probe query to ourselves and will then keep track of how many times we see it. If we see it more than twice, we assume CoreDNS has seen a forwarding loop and we halt the process.

The plugin will try to send the query for up to 30 seconds. This is done to give CoreDNS enough time to start up. Once a query has been successfully sent, loop disables itself to prevent a query of death.

The query sent is <random number>.<random number>.zone with type set to HINFO.

## SYNTAX

```
loop
```

## EXAMPLES
Start a server on the default port and load the loop and forward plugins. The forward plugin forwards to it self.

```
. {

    loop

    forward . 127.0.0.1
}
```

After CoreDNS has started it stops the process while logging:

```
plugin/loop: Loop (127.0.0.1:55953 -> :1053) detected for zone ".", see https://coredns.io/plugins/loop#troubleshooting. Query: "HINFO 4547991504243258144.3688648895315093531."
```

## LIMITATIONS
This plugin only attempts to find simple static forwarding loops at start up time. To detect a loop, the following must be true:

- the loop must be present at start up time.

- the loop must occur for the HINFO query type.

## TROUBLESHOOTING
When CoreDNS logs contain the message Loop ... detected ..., this means that the loop detection plugin has detected an infinite forwarding loop in one of the upstream DNS servers. This is a fatal error because operating with an infinite loop will consume memory and CPU until eventual out of memory death by the host.

A forwarding loop is usually caused by:

- Most commonly, CoreDNS forwarding requests directly to itself. e.g. via a loopback address such as 127.0.0.1, ::1 or 127.0.0.53

- Less commonly, CoreDNS forwarding to an upstream server that in turn, forwards requests back to CoreDNS.

To troubleshoot this problem, look in your Corefile for any forwards to the zone in which the loop was detected. Make sure that they are not forwarding to a local address or to another DNS server that is forwarding requests back to CoreDNS. If forward is using a file (e.g. /etc/resolv.conf), make sure that file does not contain local addresses.

### TROUBLESHOOTING LOOPS IN KUBERNETES CLUSTERS
When a CoreDNS Pod deployed in Kubernetes detects a loop, the CoreDNS Pod will start to "CrashLoopBackOff". This is because Kubernetes will try to restart the Pod every time CoreDNS detects the loop and exits.

A common cause of forwarding loops in Kubernetes clusters is an interaction with a local DNS cache on the host node (e.g. systemd-resolved). For example, in certain configurations systemd-resolved will put the loopback address 127.0.0.53 as a nameserver into /etc/resolv.conf. Kubernetes (via kubelet) by default will pass this /etc/resolv.conf file to all Pods using the default dnsPolicy rendering them unable to make DNS lookups (this includes CoreDNS Pods). CoreDNS uses this /etc/resolv.conf as a list of upstreams to forward requests to. Since it contains a loopback address, CoreDNS ends up forwarding requests to itself.

There are many ways to work around this issue, some are listed here:

- Add the following to your kubelet config yaml: resolvConf: <path-to-your-real-resolv-conf-file> (or via command line flag --resolv-conf deprecated in 1.10). Your "real" resolv.conf is the one that contains the actual IPs of your upstream servers, and no local/loopback address. This flag tells kubelet to pass an alternate resolv.conf to Pods. For systems using systemd-resolved, /run/systemd/resolve/resolv.conf is typically the location of the "real" resolv.conf, although this can be different depending on your distribution.

- Disable the local DNS cache on host nodes, and restore /etc/resolv.conf to the original.

- A quick and dirty fix is to edit your Corefile, replacing forward . /etc/resolv.conf with the IP address of your upstream DNS, for example forward . 8.8.8.8. But this only fixes the issue for CoreDNS, kubelet will continue to forward the invalid resolv.conf to all default dnsPolicy Pods, leaving them unable to resolve DNS.


coredns-metadata

title: coredns-metadata(7)

text:
# coredns-metadata(7)

## NAME
metadata - enables a metadata collector.

## DESCRIPTION
By enabling metadata any plugin that implements metadata.Provider interface ⟨https://godoc.org/github.com/coredns/coredns/plugin/metadata#Provider⟩ will be called for each DNS query, at the beginning of the process for that query, in order to add its own metadata to context.

The metadata collected will be available for all plugins, via the Context parameter provided in the ServeDNS function. The package (code) documentation has examples on how to inspect and retrieve metadata a plugin might be interested in.

The metadata is added by setting a label with a value in the context. These labels should be named plugin/NAME, where NAME is something descriptive. The only hard requirement the metadata plugin enforces is that the labels contain a slash. See the documentation for metadata.SetValueFunc.

The value stored is a string. The empty string signals "no metadata". See the documentation for metadata.ValueFunc on how to retrieve this.

## SYNTAX

```
metadata [ZONES... ]
```

•

ZONES zones metadata should be invoked for.

## PLUGINS
metadata.Provider interface needs to be implemented by each plugin willing to provide metadata information for other plugins. It will be called by metadata and gather the information from all plugins in context.

Note: this method should work quickly, because it is called for every request.

## EXAMPLES
The rewrite plugin uses meta data to rewrite requests.

## SEE ALSO
The Provider interface ⟨https://godoc.org/github.com/coredns/coredns/plugin/metadata#Provider⟩ and the package level ⟨https://godoc.org/github.com/coredns/coredns/plugin/metadata⟩ documentation.


coredns-metrics

title: coredns-metrics(7)

text:
# coredns-metrics(7)

## NAME
prometheus - enables Prometheus ⟨https://prometheus.io/⟩ metrics.

## DESCRIPTION
With prometheus you export metrics from CoreDNS and any plugin that has them. The default location for the metrics is localhost:9153. The metrics path is fixed to /metrics. The following metrics are exported:

- coredns_build_info{version, revision, goversion} - info about CoreDNS itself.

- coredns_panics_total{} - total number of panics.

- coredns_dns_requests_total{server, zone, proto, family, type} - total query count.

- coredns_dns_request_duration_seconds{server, zone, type} - duration to process each query.

- coredns_dns_request_size_bytes{server, zone, proto} - size of the request in bytes.

- coredns_dns_do_requests_total{server, zone} - queries that have the DO bit set

- coredns_dns_response_size_bytes{server, zone, proto} - response size in bytes.

- coredns_dns_responses_total{server, zone, rcode} - response per zone and rcode.

- coredns_plugin_enabled{server, zone, name} - indicates whether a plugin is enabled on per server and zone basis.

Each counter has a label zone which is the zonename used for the request/response.

Extra labels used are:

- server is identifying the server responsible for the request. This is a string formatted as the server's listening address: <scheme>://[<bind>]:<port>. I.e. for a "normal" DNS server this is dns://:53. If you are using the bind plugin an IP address is included, e.g.: dns://127.0.0.53:53.

- proto which holds the transport of the response ("udp" or "tcp")

- The address family (family) of the transport (1 = IP (IP version 4), 2 = IP6 (IP version 6)).

- type which holds the query type. It holds most common types (A, AAAA, MX, SOA, CNAME, PTR, TXT, NS, SRV, DS, DNSKEY, RRSIG, NSEC, NSEC3, IXFR, AXFR and ANY) and "other" which lumps together all other types.

If monitoring is enabled, queries that do not enter the plugin chain are exported under the fake name "dropped" (without a closing dot - this is never a valid domain name).

This plugin can only be used once per Server Block.

## SYNTAX

```
prometheus [ADDRESS]
```

For each zone that you want to see metrics for.

It optionally takes a bind address to which the metrics are exported; the default listens on localhost:9153. The metrics path is fixed to /metrics.

## EXAMPLES
Use an alternative listening address:

```
. {

    prometheus localhost:9253
}
```

Or via an environment variable (this is supported throughout the Corefile): export PORT=9253, and then:

```
. {

    prometheus localhost:{$PORT}
}
```

## BUGS
When reloading, the Prometheus handler is stopped before the new server instance is started. If that new server fails to start, then the initial server instance is still available and DNS queries still served, but Prometheus handler stays down. Prometheus will not reply HTTP request until a successful reload or a complete restart of CoreDNS. Only the plugins that register as Handler are visible in coredns_plugin_enabled{server, zone, name}. As of today the plugins reload and bind will not be reported.


coredns-minimal

title: coredns-minimal(7)

text:
# coredns-minimal(7)

## NAME
minimal - minimizes size of the DNS response message whenever possible.

## DESCRIPTION
The minimal plugin tries to minimize the size of the response. Depending on the response type it removes resource records from the AUTHORITY and ADDITIONAL sections.

Specifically this plugin looks at successful responses (this excludes negative responses, i.e. nodata or name error). If the successful response isn't a delegation only the RRs in the answer section are written to the client.

## SYNTAX

```
minimal
```

## EXAMPLES
Enable minimal responses:

```
example.org {

    whoami

    forward . 8.8.8.8

    minimal
}
```

## SEE ALSO
BIND 9 Configuration Reference ⟨https://bind9.readthedocs.io/en/latest/reference.html#boolean-options⟩


coredns-nsid

title: coredns-nsid(7)

text:
# coredns-nsid(7)

## NAME
nsid - adds an identifier of this server to each reply.

## DESCRIPTION
This plugin implements RFC 5001 ⟨https://tools.ietf.org/html/rfc5001⟩ and adds an EDNS0 OPT resource record to replies that uniquely identify the server. This is useful in anycast setups to see which server was responsible for generating the reply and for debugging.

This plugin can only be used once per Server Block.

## SYNTAX

```
nsid [DATA]
```

DATA is the string to use in the nsid record.

If DATA is not given, the host's name is used.

## EXAMPLES
Enable nsid:

```
example.org {

    whoami

    nsid Use The Force
}
```

And now a client with NSID support will see an OPT record with the NSID option:

```
% dig +nsid @localhost a whoami.example.org
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 46880
;; flags: qr aa rd; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 3
....
; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
; NSID: 55 73 65 20 54 68 65 20 46 6f 72 63 65 ("Use The Force")
;; QUESTION SECTION:
;whoami.example.org.        IN    A
```

## SEE ALSO
RFC 5001 ⟨https://tools.ietf.org/html/rfc5001⟩


coredns-pprof

title: coredns-pprof(7)

text:
# coredns-pprof(7)

## NAME
pprof - publishes runtime profiling data at endpoints under /debug/pprof.

## DESCRIPTION
You can visit /debug/pprof on your site for an index of the available endpoints. By default it will listen on localhost:6053.

This is a debugging tool. Certain requests (such as collecting execution traces) can be slow. If you use pprof on a live server, consider restricting access or enabling it only temporarily.

This plugin can only be used once per Server Block.

## SYNTAX

```
pprof [ADDRESS]
```

Optionally pprof takes an address; the default is localhost:6053.

An extra option can be set with this extended syntax:

```
pprof [ADDRESS] {

   block [RATE]
}
```

•

block option enables block profiling, RATE defaults to 1. RATE must be a positive value. See Diagnostics, chapter profiling ⟨https://golang.org/doc/diagnostics.html⟩ and runtime.SetBlockProfileRate ⟨https://golang.org/pkg/runtime/#SetBlockProfileRate⟩ for what block profiling entails.

## EXAMPLES
Enable a pprof endpoint:

```
. {

    pprof
}
```

And use the pprof tool to get statistics: go tool pprof http://localhost:6053.

Listen on an alternate address:

```
. {

    pprof 10.9.8.7:6060
}
```

Listen on an all addresses on port 6060, and enable block profiling

```
. {

    pprof :6060 {

       block

    }
}
```

## SEE ALSO
See Go's pprof documentation ⟨https://golang.org/pkg/net/http/pprof/⟩ and Profiling Go Programs ⟨https://blog.golang.org/profiling-go-programs⟩.

See runtime.SetBlockProfileRate ⟨https://golang.org/pkg/runtime/#SetBlockProfileRate⟩ for background on block profiling.


coredns-ready

title: coredns-ready(7)

text:
# coredns-ready(7)

## NAME
ready - enables a readiness check HTTP endpoint.

## DESCRIPTION
By enabling ready an HTTP endpoint on port 8181 will return 200 OK, when all plugins that are able to signal readiness have done so. If some are not ready yet the endpoint will return a 503 with the body containing the list of plugins that are not ready. Once a plugin has signaled it is ready it will not be queried again.

Each Server Block that enables the ready plugin will have the plugins in that server block report readiness into the /ready endpoint that runs on the same port. This also means that the same plugin with different configurations (in potentially different Server Blocks) will have their readiness reported as the union of their respective readinesses.

## SYNTAX

```
ready [ADDRESS]
```

ready optionally takes an address; the default is :8181. The path is fixed to /ready. The readiness endpoint returns a 200 response code and the word "OK" when this server is ready. It returns a 503 otherwise and the list of plugins that are not ready.

## PLUGINS
Any plugin wanting to signal readiness will need to implement the ready.Readiness interface by implementing a method Ready() bool that returns true when the plugin is ready and false otherwise.

## EXAMPLES
Let ready report readiness for both the . and example.org servers (assuming the whois plugin also exports readiness):

```
. {

    ready

    erratic
}
example.org {

    ready

    whoami
}
```

Run ready on a different port.

```
. {

    ready localhost:8091
}
```


coredns-reload

title: coredns-reload(7)

text:
# coredns-reload(7)

## NAME
reload - allows automatic reload of a changed Corefile.

## DESCRIPTION
This plugin allows automatic reload of a changed Corefile. To enable automatic reloading of zone file changes, use the auto plugin.

This plugin periodically checks if the Corefile has changed by reading it and calculating its MD5 checksum. If the file has changed, it reloads CoreDNS with the new Corefile. This eliminates the need to send a SIGHUP or SIGUSR1 after changing the Corefile.

The reloads are graceful - you should not see any loss of service when the reload happens. Even if the new Corefile has an error, CoreDNS will continue to run the old config and an error message will be printed to the log. But see the Bugs section for failure modes.

In some environments (for example, Kubernetes), there may be many CoreDNS instances that started very near the same time and all share a common Corefile. To prevent these all from reloading at the same time, some jitter is added to the reload check interval. This is jitter from the perspective of multiple CoreDNS instances; each instance still checks on a regular interval, but all of these instances will have their reloads spread out across the jitter duration. This isn't strictly necessary given that the reloads are graceful, and can be disabled by setting the jitter to 0s.

Jitter is re-calculated whenever the Corefile is reloaded.

This plugin can only be used once per Server Block.

## SYNTAX

```
reload [INTERVAL] [JITTER]
```

The plugin will check for changes every INTERVAL, subject to +/- the JITTER duration.

•

INTERVAL and JITTER are Golang durations ⟨https://golang.org/pkg/time/#ParseDuration⟩. The default INTERVAL is 30s, default JITTER is 15s, the minimal value for INTERVAL is 2s, and for JITTER it is 1s. If JITTER is more than half of INTERVAL, it will be set to half of INTERVAL

## EXAMPLES
Check with the default intervals:

```
. {

    reload

    erratic
}
```

Check every 10 seconds (jitter is automatically set to 10 / 2 = 5 in this case):

```
. {

    reload 10s

    erratic
}
```

## BUGS
The reload happens without data loss (i.e. DNS queries keep flowing), but there is a corner case where the reload fails, and you loose functionality. Consider the following Corefile:

```
. {

    health :8080

    whoami
}
```

CoreDNS starts and serves health from :8080. Now you change :8080 to :443 not knowing a process is already listening on that port. The process reloads and performs the following steps:

1.

close the listener on 8080

2.

reload and parse the config again

3.

fail to start a new listener on 443

4.

fail loading the new Corefile, abort and keep using the old process

After the aborted attempt to reload we are left with the old processes running, but the listener is closed in step 1; so the health endpoint is broken. The same can happen in the prometheus plugin.

In general be careful with assigning new port and expecting reload to work fully.

In CoreDNS v1.6.0 and earlier any import statements are not discovered by this plugin. This means if any of these imported files changes the reload plugin is ignorant of that fact. CoreDNS v1.7.0 and later does parse the Corefile and supports detecting changes in imported files.

## METRICS
If monitoring is enabled (via the prometheus plugin) then the following metric is exported:

- coredns_reload_failed_total{} - counts the number of failed reload attempts.

- coredns_reload_version_info{hash, value} - record the hash value during reload.

Currently the type of hash is "md5", the value is the returned hash value.

## SEE ALSO
See coredns-import(7) and corefile(5).


coredns-rewrite

title: coredns-rewrite(7)

text:
# coredns-rewrite(7)

## NAME
rewrite - performs internal message rewriting.

## DESCRIPTION
Rewrites are invisible to the client. There are simple rewrites (fast) and complex rewrites (slower), but they're powerful enough to accommodate most dynamic back-end applications.

## SYNTAX
A simplified/easy-to-digest syntax for rewrite is...

```
rewrite [continue|stop] FIELD [FROM TO|FROM TTL]
```

•

FIELD indicates what part of the request/response is being re-written.

–

type - the type field of the request will be rewritten. FROM/TO must be a DNS record type (A, MX, etc.); e.g., to rewrite ANY queries to HINFO, use rewrite type ANY HINFO.

–

class - the class of the message will be rewritten. FROM/TO must be a DNS class type (IN, CH, or HS); e.g., to rewrite CH queries to IN use rewrite class CH IN.

–

name - the query name in the request is rewritten; by default this is a full match of the name, e.g., rewrite name example.net example.org. Other match types are supported, see the Name Field Rewrites section below.

–

answer name - the query name in the response is rewritten. This option has special restrictions and requirements, in particular it must always combined with a name rewrite. See below in the Response Rewrites section.

–

edns0 - an EDNS0 option can be appended to the request as described below in the EDNS0 Options section.

–

ttl - the TTL value in the response is rewritten.

- FROM is the name (exact, suffix, prefix, substring, or regex) or type to match

- TO is the destination name or type to rewrite to

- TTL is the number of seconds to set the TTL value to

If you specify multiple rules and an incoming query matches multiple rules, the rewrite will behave as follows:

- continue will continue applying the next rule in the rule list.

- stop will consider the current rule the last rule and will not continue. The default behaviour is stop

## EXAMPLES

### NAME FIELD REWRITES
The rewrite plugin offers the ability to match the name in the question section of a DNS request. The match could be exact, a substring match, or based on a prefix, suffix, or regular expression. If the newly used name is not a legal domain name, the plugin returns an error to the client.

The syntax for name rewriting is as follows:

```
rewrite [continue|stop] name [exact|prefix|suffix|substring|regex] STRING STRING
```

The match type, e.g., exact, substring, etc., triggers rewrite:

- exact (default): on an exact match of the name in the question section of a request

- substring: on a partial match of the name in the question section of a request

- prefix: when the name begins with the matching string

- suffix: when the name ends with the matching string

- regex: when the name in the question section of a request matches a regular expression

If the match type is omitted, the exact match type is assumed.

The following instruction allows rewriting names in the query that contain the substring service.us-west-1.example.org:

```
rewrite name substring service.us-west-1.example.org service.us-west-1.consul
```

Thus:

- Incoming Request Name: ftp.service.us-west-1.example.org

- Rewritten Request Name: ftp.service.us-west-1.consul

The following instruction uses regular expressions. Names in requests matching the regular expression (.*)-(us-west-1).example.org are replaced with {1}.service.{2}.consul, where {1} and {2} are regular expression match groups.

```
rewrite name regex (.*)-(us-west-1)\.example\.org {1}.service.{2}.consul
```

Thus:

- Incoming Request Name: ftp-us-west-1.example.org

- Rewritten Request Name: ftp.service.us-west-1.consul

The following example rewrites the schmoogle.com suffix to google.com.

```
rewrite name suffix .schmoogle.com. .google.com.
```

### RESPONSE REWRITES
When rewriting incoming DNS requests' names, CoreDNS re-writes the QUESTION SECTION section of the requests. It may be necessary to rewrite the ANSWER SECTION of the requests, because some DNS resolvers treat mismatches between the QUESTION SECTION and ANSWER SECTION as a man-in-the-middle attack (MITM).

For example, a user tries to resolve ftp-us-west-1.coredns.rocks. The CoreDNS configuration file has the following rule:

```
rewrite name regex (.*)-(us-west-1)\.coredns\.rocks {1}.service.{2}.consul
```

CoreDNS rewrote the request from ftp-us-west-1.coredns.rocks to ftp.service.us-west-1.consul and ultimately resolved it to 3 records. The resolved records, in the ANSWER SECTION below, were not from coredns.rocks, but rather from service.us-west-1.consul.

```
$ dig @10.1.1.1 ftp-us-west-1.coredns.rocks
;; QUESTION SECTION:
;ftp-us-west-1.coredns.rocks. IN A
;; ANSWER SECTION:
ftp.service.us-west-1.consul. 0    IN A    10.10.10.10
ftp.service.us-west-1.consul. 0    IN A    10.20.20.20
ftp.service.us-west-1.consul. 0    IN A    10.30.30.30
```

The above is a mismatch between the question asked and the answer provided.

The following configuration snippet allows for rewriting of the ANSWER SECTION, provided that the QUESTION SECTION was rewritten:

```
    rewrite stop {

        name regex (.*)-(us-west-1)\.coredns\.rocks {1}.service.{2}.consul

        answer name (.*)\.service\.(us-west-1)\.consul {1}-{2}.coredns.rocks

    }
```

Now, the ANSWER SECTION matches the QUESTION SECTION:

```
$ dig @10.1.1.1 ftp-us-west-1.coredns.rocks
;; QUESTION SECTION:
;ftp-us-west-1.coredns.rocks. IN A
;; ANSWER SECTION:
ftp-us-west-1.coredns.rocks. 0    IN A    10.10.10.10
ftp-us-west-1.coredns.rocks. 0    IN A    10.20.20.20
ftp-us-west-1.coredns.rocks. 0    IN A    10.30.30.30
```

It is also possible to rewrite other values returned in the DNS response records (e.g. the server names returned in SRV and MX records). This can be enabled by adding the answer value to a name regex rule as specified below. answer value takes a regular expression and a rewrite name as parameters and works in the same way as the answer name rule.

Note that names in the AUTHORITY SECTION and ADDITIONAL SECTION will also be rewritten following the specified rules. The names returned by the following record types: CNAME, DNAME, SOA, SRV, MX, NAPTR, NS will be rewritten if the answer value rule is specified.

The syntax for the rewrite of DNS request and response is as follows:

```
rewrite [continue|stop] {

    name regex STRING STRING

    answer name STRING STRING

    [answer value STRING STRING]
}
```

Note that the above syntax is strict. For response rewrites, only name rules are allowed to match the question section, and only by match type regex. The answer rewrite must be after the name, as in the syntax example.

An alternate syntax for rewriting a DNS request and response is as follows:

```
rewrite [continue|stop] name regex STRING STRING answer name STRING STRING [answer value STRING STRING]
```

When using exact name rewrite rules, the answer gets rewritten automatically, and there is no need to define answer name. The rule below rewrites the name in a request from RED to BLUE, and subsequently rewrites the name in a corresponding response from BLUE to RED. The client in the request would see only RED and no BLUE.

```
rewrite [continue|stop] name exact RED BLUE
```

### TTL FIELD REWRITES
At times, the need to rewrite a TTL value could arise. For example, a DNS server may not cache records with a TTL of zero (0). An administrator may want to increase the TTL to ensure it is cached, e.g., by increasing it to 15 seconds.

In the below example, the TTL in the answers for coredns.rocks domain are being set to 15:

```
    rewrite continue {

        ttl regex (.*)\.coredns\.rocks 15

    }
```

By the same token, an administrator may use this feature to prevent or limit caching by setting the TTL value really low.

The syntax for the TTL rewrite rule is as follows. The meaning of exact|prefix|suffix|substring|regex is the same as with the name rewrite rules.

```
rewrite [continue|stop] ttl [exact|prefix|suffix|substring|regex] STRING SECONDS
```

## EDNS0 OPTIONS
Using the FIELD edns0, you can set, append, or replace specific EDNS0 options in the request.

- replace will modify any "matching" option with the specified option. The criteria for "matching" varies based on EDNS0 type.

- append will add the option only if no matching option exists

- set will modify a matching option or add one if none is found

Currently supported are EDNS0_LOCAL, EDNS0_NSID and EDNS0_SUBNET.

### EDNS0_LOCAL
This has two fields, code and data. A match is defined as having the same code. Data may be a string or a variable.

•

A string data is treated as hex if it starts with 0x. Example:

```
. {

    rewrite edns0 local set 0xffee 0x61626364

    whoami
}
```

rewrites the first local option with code 0xffee, setting the data to "abcd". This is equivalent to:

```
. {

    rewrite edns0 local set 0xffee abcd
}
```

- A variable data is specified with a pair of curly brackets {}. Following are the supported variables: {qname}, {qtype}, {clientip}, {clientport}, {protocol}, {serverip}, {serverport}.

- If the metadata plugin is enabled, then labels are supported as variables if they are presented within curly brackets. The variable data will be replaced with the value associated with that label. If that label is not provided, the variable will be silently substituted with an empty string.

Examples:

```
rewrite edns0 local set 0xffee {client_ip}
```

The following example uses metadata and an imaginary "some-plugin" that would provide "some-label" as metadata information.

```
metadata
some-plugin
rewrite edns0 local set 0xffee {some-plugin/some-label}
```

### EDNS0_NSID
This has no fields; it will add an NSID option with an empty string for the NSID. If the option already exists and the action is replace or set, then the NSID in the option will be set to the empty string.

### EDNS0_SUBNET
This has two fields, IPv4 bitmask length and IPv6 bitmask length. The bitmask length is used to extract the client subnet from the source IP address in the query.

Example:

```
rewrite edns0 subnet set 24 56
```

- If the query's source IP address is an IPv4 address, the first 24 bits in the IP will be the network subnet.

- If the query's source IP address is an IPv6 address, the first 56 bits in the IP will be the network subnet.

## FULL SYNTAX
The full plugin usage syntax is harder to digest...

```
rewrite [continue|stop] {type|class|edns0|name [exact|prefix|suffix|substring|regex [FROM TO answer name]]} FROM TO
```

The syntax above doesn't cover the multi-line block option for specifying a name request+response rewrite rule described in the Response Rewrite section.


coredns-root

title: coredns-root(7)

text:
# coredns-root(7)

## NAME
root - simply specifies the root of where to find (zone) files.

## DESCRIPTION
The default root is the current working directory of CoreDNS. The root plugin allows you to change this. A relative root path is relative to the current working directory.

This plugin can only be used once per Server Block.

## SYNTAX

```
root PATH
```

PATH is the directory to set as CoreDNS' root.

## EXAMPLES
Serve zone data (when the file plugin is used) from /etc/coredns/zones:

```
. {

    root /etc/coredns/zones
}
```


title: coredns-route53(7)

text:
# coredns-route53(7)

## NAME
route53 - enables serving zone data from AWS route53.

## DESCRIPTION
The route53 plugin is useful for serving zones from resource record sets in AWS route53. This plugin supports all Amazon Route 53 records (https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/ResourceRecordTypes.html ⟨https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/ResourceRecordTypes.html⟩). The route53 plugin can be used when coredns is deployed on AWS or elsewhere.

## SYNTAX

```
route53 [ZONE:HOSTED_ZONE_ID...] {

    aws_access_key [AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY]

    credentials PROFILE [FILENAME]

    fallthrough [ZONES...]

    refresh DURATION
}
```

- ZONE the name of the domain to be accessed. When there are multiple zones with overlapping domains (private vs. public hosted zone), CoreDNS does the lookup in the given order here. Therefore, for a non-existing resource record, SOA response will be from the rightmost zone.

- HOSTED_ZONE_ID the ID of the hosted zone that contains the resource record sets to be accessed.

- AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY the AWS access key ID and secret access key to be used when query AWS (optional). If they are not provided, then coredns tries to access AWS credentials the same way as AWS CLI, e.g., environmental variables, AWS credentials file, instance profile credentials, etc.

- credentials is used for reading the credential FILENAME and setting the PROFILE name for a given zone. PROFILE is the AWS account profile name. Defaults to default. FILENAME is the AWS credentials filename, defaults to ~/.aws/credentials.

- fallthrough If zone matches and no record can be generated, pass request to the next plugin. If ZONES is omitted, then fallthrough happens for all zones for which the plugin is authoritative. If specific zones are listed (for example in-addr.arpa and ip6.arpa), then only queries for those zones will be subject to fallthrough.

- refresh can be used to control how long between record retrievals from Route 53. It requires a duration string as a parameter to specify the duration between update cycles. Each update cycle may result in many AWS API calls depending on how many domains use this plugin and how many records are in each. Adjusting the update frequency may help reduce the potential of API rate-limiting imposed by AWS.

- DURATION A duration string. Defaults to 1m. If units are unspecified, seconds are assumed.

## EXAMPLES
Enable route53 with implicit AWS credentials and resolve CNAMEs via 10.0.0.1:

```
example.org {

    route53 example.org.:Z1Z2Z3Z4DZ5Z6Z7
}
. {

    forward . 10.0.0.1
}
```

Enable route53 with explicit AWS credentials:

```
example.org {

    route53 example.org.:Z1Z2Z3Z4DZ5Z6Z7 {

      aws_access_key AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY

    }
}
```

Enable route53 with fallthrough:

```
. {

    route53 example.org.:Z1Z2Z3Z4DZ5Z6Z7 example.gov.:Z654321543245 {

      fallthrough example.gov.

    }
}
```

Enable route53 with multiple hosted zones with the same domain:

```
example.org {

    route53 example.org.:Z1Z2Z3Z4DZ5Z6Z7 example.org.:Z93A52145678156
}
```

Enable route53 and refresh records every 3 minutes

```
example.org {

    route53 example.org.:Z1Z2Z3Z4DZ5Z6Z7 {

      refresh 3m

    }
}
```


coredns-secondary

title: coredns-secondary(7)

text:
# coredns-secondary(7)

## NAME
secondary - enables serving a zone retrieved from a primary server.

## DESCRIPTION
With secondary you can transfer (via AXFR) a zone from another server. The retrieved zone is not committed to disk (a violation of the RFC). This means restarting CoreDNS will cause it to retrieve all secondary zones.

## SYNTAX

```
secondary [ZONES...]
```

•

ZONES zones it should be authoritative for. If empty, the zones from the configuration block are used. Note that without a remote address to get the zone from, the above is not that useful.

A working syntax would be:

```
secondary [zones...] {

    transfer from ADDRESS [ADDRESS...]
}
```

•

transfer from specifies from which ADDRESS to fetch the zone. It can be specified multiple times; if one does not work, another will be tried. Transfering this zone outwards again can be done by enabling the transfer plugin.

When a zone is due to be refreshed (refresh timer fires) a random jitter of 5 seconds is applied, before fetching. In the case of retry this will be 2 seconds. If there are any errors during the transfer in, the transfer fails; this will be logged.

## EXAMPLES
Transfer example.org from 10.0.1.1, and if that fails try 10.1.2.1.

```
example.org {

    secondary {

        transfer from 10.0.1.1 10.1.2.1

    }
}
```

Or re-export the retrieved zone to other secondaries.

```
example.net {

    secondary {

        transfer from 10.1.2.1

    }

    transfer {

        to *

    }
}
```

## BUGS
Only AXFR is supported and the retrieved zone is not committed to disk.

## SEE ALSO
See the transfer plugin to enable zone transfers to other servers.


coredns-sign

title: coredns-sign(7)

text:
# coredns-sign(7)

## NAME
sign - adds DNSSEC records to zone files.

## DESCRIPTION
The sign plugin is used to sign (see RFC 6781) zones. In this process DNSSEC resource records are added. The signatures that sign the resource records sets have an expiration date, this means the signing process must be repeated before this expiration data is reached. Otherwise the zone's data will go BAD (RFC 4035, Section 5.5). The sign plugin takes care of this.

Only NSEC is supported, sign does not support NSEC3.

Sign works in conjunction with the file and auto plugins; this plugin signs the zones files, auto and file serve the zones data.

For this plugin to work at least one Common Signing Key, (see coredns-keygen(1)) is needed. This key (or keys) will be used to sign the entire zone. Sign does not support the ZSK/KSK split, nor will it do key or algorithm rollovers - it just signs.

Sign will:

•

(Re)-sign the zone with the CSK(s) when:

–

the last time it was signed is more than a 6 days ago. Each zone will have some jitter applied to the inception date.

–

the signature only has 14 days left before expiring.

Both these dates are only checked on the SOA's signature(s).

- Create RRSIGs that have an inception of -3 hours (minus a jitter between 0 and 18 hours) and a expiration of +32 (plus a jitter between 0 and 5 days) days for every given DNSKEY.

- Add NSEC records for all names in the zone. The TTL for these is the negative cache TTL from the SOA record.

- Add or replace all apex CDS/CDNSKEY records with the ones derived from the given keys. For each key two CDS are created one with SHA1 and another with SHA256.

- Update the SOA's serial number to the Unix epoch of when the signing happens. This will overwrite any previous serial number.

There are two ways that dictate when a zone is signed. Normally every 6 days (plus jitter) it will be resigned. If for some reason we fail this check, the 14 days before expiring kicks in.

Keys are named (following BIND9): K<name>+<alg>+<id>.key and K<name>+<alg>+<id>.private. The keys must not be included in your zone; they will be added by sign. These keys can be generated with coredns-keygen or BIND9's dnssec-keygen. You don't have to adhere to this naming scheme, but then you need to name your keys explicitly, see the keys file directive.

A generated zone is written out in a file named db.<name>.signed in the directory named by the directory directive (which defaults to /var/lib/coredns).

## SYNTAX

```
sign DBFILE [ZONES...] {

    key file|directory KEY...|DIR...

    directory DIR
}
```

- DBFILE the zone database file to read and parse. If the path is relative, the path from the root plugin will be prepended to it.

- ZONES zones it should be sign for. If empty, the zones from the configuration block are used.

- key specifies the key(s) (there can be multiple) to sign the zone. If file is used the KEY's filenames are used as is. If directory is used, sign will look in DIR for K<name>+<alg>+<id> files. Any metadata in these files (Activate, Publish, etc.) is ignored. These keys must also be Key Signing Keys (KSK).

- directory specifies the DIR where CoreDNS should save zones that have been signed. If not given this defaults to /var/lib/coredns. The zones are saved under the name db.<name>.signed. If the path is relative the path from the root plugin will be prepended to it.

Keys can be generated with coredns-keygen, to create one for use in the sign plugin, use: coredns-keygen example.org or dnssec-keygen -a ECDSAP256SHA256 -f KSK example.org.

## EXAMPLES
Sign the example.org zone contained in the file db.example.org and write the result to ./db.example.org.signed to let the file plugin pick it up and serve it. The keys used are read from /etc/coredns/keys/Kexample.org.key and /etc/coredns/keys/Kexample.org.private.

```
example.org {

    file db.example.org.signed

    sign db.example.org {

        key file /etc/coredns/keys/Kexample.org

        directory .

    }
}
```

Running this leads to the following log output (note the timers in this example have been set to shorter intervals).

```
[WARNING] plugin/file: Failed to open "open /tmp/db.example.org.signed: no such file or directory": trying again in 1m0s
[INFO] plugin/sign: Signing "example.org." because open /tmp/db.example.org.signed: no such file or directory
[INFO] plugin/sign: Successfully signed zone "example.org." in "/tmp/db.example.org.signed" with key tags "59725" and 1564766865 SOA serial, elapsed 9.357933ms, next: 2019-08-02T22:27:45.270Z
[INFO] plugin/file: Successfully reloaded zone "example.org." in "/tmp/db.example.org.signed" with serial 1564766865
```

Or use a single zone file for multiple zones, note that the ZONES are repeated for both plugins. Also note this outputs multiple signed output files. Here we use the default output directory /var/lib/coredns.

```
. {

    file /var/lib/coredns/db.example.org.signed example.org

    file /var/lib/coredns/db.example.net.signed example.net

    sign db.example.org example.org example.net {

        key directory /etc/coredns/keys

    }
}
```

This is the same configuration, but the zones are put in the server block, but note that you still need to specify what file is served for what zone in the file plugin:

```
example.org example.net {

    file var/lib/coredns/db.example.org.signed example.org

    file var/lib/coredns/db.example.net.signed example.net

    sign db.example.org {

        key directory /etc/coredns/keys

    }
}
```

Be careful to fully list the origins you want to sign, if you don't:

```
example.org example.net {

    sign plugin/sign/testdata/db.example.org miek.org {

        key file /etc/coredns/keys/Kexample.org

    }
}
```

This will lead to db.example.org be signed twice, as this entire section is parsed twice because you have specified the origins example.org and example.net in the server block.

Forcibly resigning a zone can be accomplished by removing the signed zone file (CoreDNS will keep on serving it from memory), and sending SIGUSR1 to the process to make it reload and resign the zone file.

## SEE ALSO
The DNSSEC RFCs: RFC 4033, RFC 4034 and RFC 4035. And the BCP on DNSSEC, RFC 6781. Further more the manual pages coredns-keygen(1) and dnssec-keygen(8). And the file plugin's documentation.

Coredns-keygen can be found at https://github.com/coredns/coredns-utils ⟨https://github.com/coredns/coredns-utils⟩ in the coredns-keygen directory.

Other useful DNSSEC tools can be found in ldns ⟨https://nlnetlabs.nl/projects/ldns/about/⟩, e.g. ldns-key2ds to create DS records from DNSKEYs.

## BUGS
keys directory is not implemented.


coredns-template

title: coredns-template(7)

text:
# coredns-template(7)

## NAME
template - allows for dynamic responses based on the incoming query.

## DESCRIPTION
The template plugin allows you to dynamically respond to queries by just writing a (Go) template.

## SYNTAX

```
template CLASS TYPE [ZONE...] {

    match REGEX...

    answer RR

    additional RR

    authority RR

    rcode CODE

    fallthrough [ZONE...]
}
```

- CLASS the query class (usually IN or ANY).

- TYPE the query type (A, PTR, ... can be ANY to match all types).

- ZONE the zone scope(s) for this template. Defaults to the server zones.

- REGEX Go regexp ⟨https://golang.org/pkg/regexp/⟩ that are matched against the incoming question name. Specifying no regex matches everything (default: .*). First matching regex wins.

- answer|additional|authority RR A RFC 1035 ⟨https://tools.ietf.org/html/rfc1035#section-5⟩ style resource record fragment built by a Go template ⟨https://golang.org/pkg/text/template/⟩ that contains the reply.

- rcode CODE A response code (NXDOMAIN, SERVFAIL, ...). The default is SUCCESS.

- fallthrough Continue with the next plugin if the zone matched but no regex matched. If specific zones are listed (for example in-addr.arpa and ip6.arpa), then only queries for those zones will be subject to fallthrough.

At least one answer or rcode directive is needed (e.g. rcode NXDOMAIN).

Also see ⟨#also-see⟩ contains an additional reading list.

## TEMPLATES
Each resource record is a full-featured Go template ⟨https://golang.org/pkg/text/template/⟩ with the following predefined data

- .Zone the matched zone string (e.g. example.).

- .Name the query name, as a string (lowercased).

- .Class the query class (usually IN).

- .Type the RR type requested (e.g. PTR).

- .Match an array of all matches. index .Match 0 refers to the whole match.

- .Group a map of the named capture groups.

- .Message the complete incoming DNS message.

- .Question the matched question section.

- .Remote client’s IP address

- .Meta a function that takes a metadata name and returns the value, if the metadata plugin is enabled. For example, .Meta "kubernetes/client-namespace"

The output of the template must be a RFC 1035 ⟨https://tools.ietf.org/html/rfc1035⟩ style resource record (commonly referred to as a "zone file").

WARNING there is a syntactical problem with Go templates and CoreDNS config files. Expressions

like {{$var}} will be interpreted as a reference to an environment variable by CoreDNS (and

Caddy) while {{ $var }} will work. See Bugs ⟨#bugs⟩ and corefile(5).

## METRICS
If monitoring is enabled (via the prometheus plugin) then the following metrics are exported:

- coredns_template_matches_total{server, regex} the total number of matched requests by regex.

- coredns_template_template_failures_total{server, regex,section,template} the number of times the Go templating failed. Regex, section and template label values can be used to map the error back to the config file.

- coredns_template_rr_failures_total{server, regex,section,template} the number of times the templated resource record was invalid and could not be parsed. Regex, section and template label values can be used to map the error back to the config file.

Both failure cases indicate a problem with the template configuration. The server label indicates the server incrementing the metric, see the metrics plugin for details.

## EXAMPLES

### RESOLVE EVERYTHING TO NXDOMAIN
The most simplistic template is

```
. {

    template ANY ANY {

      rcode NXDOMAIN

    }
}
```

1.

This template uses the default zone (. or all queries)

2.

All queries will be answered (no fallthrough)

3.

The answer is always NXDOMAIN

### RESOLVE .INVALID AS NXDOMAIN
The .invalid domain is a reserved TLD (see RFC 2606 Reserved Top Level DNS Names ⟨https://tools.ietf.org/html/rfc2606#section-2⟩) to indicate invalid domains.

```
. {

    forward . 8.8.8.8

    template ANY ANY invalid {

      rcode NXDOMAIN

      authority "invalid. 60 {{ .Class }} SOA ns.invalid. hostmaster.invalid. (1 60 60 60 60)"

    }
}
```

1.

A query to .invalid will result in NXDOMAIN (rcode)

2.

A dummy SOA record is sent to hand out a TTL of 60s for caching purposes

3.

Querying .invalid in the CH class will also cause a NXDOMAIN/SOA response

4.

The default regex is .*

### BLOCK INVALID SEARCH DOMAIN COMPLETIONS
Imagine you run example.com with a datacenter dc1.example.com. The datacenter domain is part of the DNS search domain. However something.example.com.dc1.example.com would indicate a fully qualified domain name (something.example.com) that inadvertently has the default domain or search path (dc1.example.com) added.

```
. {

    forward . 8.8.8.8

    template IN ANY example.com.dc1.example.com {

      rcode NXDOMAIN

      authority "{{ .Zone }} 60 IN SOA ns.example.com hostmaster.example.com (1 60 60 60 60)"

    }
}
```

A more verbose regex based equivalent would be

```
. {

    forward . 8.8.8.8

    template IN ANY example.com {

      match "example\.com\.(dc1\.example\.com\.)$"

      rcode NXDOMAIN

      authority "{{ index .Match 1 }} 60 IN SOA ns.{{ index .Match 1 }} hostmaster.{{ index .Match 1 }} (1 60 60 60 60)"

      fallthrough

    }
}
```

The regex-based version can do more complex matching/templating while zone-based templating is easier to read and use.

### RESOLVE A/PTR FOR .EXAMPLE

```
. {

    forward . 8.8.8.8

    # ip-a-b-c-d.example A a.b.c.d

    template IN A example {

      match (^|[.])ip-(?P<a>[0-9]*)-(?P<b>[0-9]*)-(?P<c>[0-9]*)-(?P<d>[0-9]*)[.]example[.]$

      answer "{{ .Name }} 60 IN A {{ .Group.a }}.{{ .Group.b }}.{{ .Group.c }}.{{ .Group.d }}"

      fallthrough

    }

    # d.c.b.a.in-addr.arpa PTR ip-a-b-c-d.example

    template IN PTR in-addr.arpa {

      match ^(?P<d>[0-9]*)[.](?P<c>[0-9]*)[.](?P<b>[0-9]*)[.](?P<a>[0-9]*)[.]in-addr[.]arpa[.]$

      answer "{{ .Name }} 60 IN PTR ip-{{ .Group.a }}-{{ .Group.b }}-{{ .Group.c }}-{{ .Group.d }}.example."

    }
}
```

An IPv4 address consists of 4 bytes, a.b.c.d. Named groups make it less error-prone to reverse the IP address in the PTR case. Try to use named groups to explain what your regex and template are doing.

Note that the A record is actually a wildcard: any subdomain of the IP address will resolve to the IP address.

Having templates to map certain PTR/A pairs is a common pattern.

Fallthrough is needed for mixed domains where only some responses are templated.

### RESOLVE MULTIPLE IP PATTERNS

```
. {

    forward . 8.8.8.8

    template IN A example {

      match "^ip-(?P<a>10)-(?P<b>[0-9]*)-(?P<c>[0-9]*)-(?P<d>[0-9]*)[.]dc[.]example[.]$"

      match "^(?P<a>[0-9]*)[.](?P<b>[0-9]*)[.](?P<c>[0-9]*)[.](?P<d>[0-9]*)[.]ext[.]example[.]$"

      answer "{{ .Name }} 60 IN A {{ .Group.a}}.{{ .Group.b }}.{{ .Group.c }}.{{ .Group.d }}"

      fallthrough

    }
}
```

Named capture groups can be used to template one response for multiple patterns.

### RESOLVE A AND MX RECORDS FOR IP TEMPLATES IN .EXAMPLE

```
. {

    forward . 8.8.8.8

    template IN A example {

      match ^ip-10-(?P<b>[0-9]*)-(?P<c>[0-9]*)-(?P<d>[0-9]*)[.]example[.]$

      answer "{{ .Name }} 60 IN A 10.{{ .Group.b }}.{{ .Group.c }}.{{ .Group.d }}"

      fallthrough

    }

    template IN MX example {

      match ^ip-10-(?P<b>[0-9]*)-(?P<c>[0-9]*)-(?P<d>[0-9]*)[.]example[.]$

      answer "{{ .Name }} 60 IN MX 10 {{ .Name }}"

      additional "{{ .Name }} 60 IN A 10.{{ .Group.b }}.{{ .Group.c }}.{{ .Group.d }}"

      fallthrough

    }
}
```

### ADDING AUTHORITATIVE NAMESERVERS TO THE RESPONSE

```
. {

    forward . 8.8.8.8

    template IN A example {

      match ^ip-10-(?P<b>[0-9]*)-(?P<c>[0-9]*)-(?P<d>[0-9]*)[.]example[.]$

      answer "{{ .Name }} 60 IN A 10.{{ .Group.b }}.{{ .Group.c }}.{{ .Group.d }}"

      authority  "example. 60 IN NS ns0.example."

      authority  "example. 60 IN NS ns1.example."

      additional "ns0.example. 60 IN A 203.0.113.8"

      additional "ns1.example. 60 IN A 198.51.100.8"

      fallthrough

    }

    template IN MX example {

      match ^ip-10-(?P<b>[0-9]*)-(?P<c>[0-9]*)-(?P<d>[0-9]*)[.]example[.]$

      answer "{{ .Name }} 60 IN MX 10 {{ .Name }}"

      additional "{{ .Name }} 60 IN A 10.{{ .Group.b }}.{{ .Group.c }}.{{ .Group.d }}"

      authority  "example. 60 IN NS ns0.example."

      authority  "example. 60 IN NS ns1.example."

      additional "ns0.example. 60 IN A 203.0.113.8"

      additional "ns1.example. 60 IN A 198.51.100.8"

      fallthrough

    }
}
```

## ALSO SEE

- Go regexp ⟨https://golang.org/pkg/regexp/⟩ for details about the regex implementation

- RE2 syntax reference ⟨https://github.com/google/re2/wiki/Syntax⟩ for details about the regex syntax

- RFC 1034 ⟨https://tools.ietf.org/html/rfc1034#section-3.6.1⟩ and RFC 1035 ⟨https://tools.ietf.org/html/rfc1035#section-5⟩ for the resource record format

- Go template ⟨https://golang.org/pkg/text/template/⟩ for the template language reference

## BUGS
CoreDNS supports caddyfile environment variables ⟨https://caddyserver.com/docs/caddyfile#env⟩ with notion of {$ENV_VAR}. This parser feature will break Go template variables ⟨https://golang.org/pkg/text/template/#hdr-Variables⟩ notations like{{$variable}}. The equivalent notation {{ $variable }} will work. Try to avoid Go template variables in the context of this plugin.


coredns-timeouts

title: coredns-timeouts(7)

text:
# coredns-timeouts(7)

## NAME
timeouts - allows you to configure the server read, write and idle timeouts for the TCP, TLS and DoH servers.

## DESCRIPTION
CoreDNS is configured with sensible timeouts for server connections by default. However in some cases for example where CoreDNS is serving over a slow mobile data connection the default timeouts are not optimal.

Additionally some routers hold open connections when using DNS over TLS or DNS over HTTPS. Allowing a longer idle timeout helps performance and reduces issues with such routers.

The timeouts "plugin" allows you to configure CoreDNS server read, write and idle timeouts.

## SYNTAX

```
timeouts {

    read DURATION

    write DURATION

    idle DURATION
}
```

For any timeouts that are not provided, default values are used which may vary depending on the server type. At least one timeout must be specified otherwise the entire timeouts block should be omitted.

## EXAMPLES
Start a DNS-over-TLS server that picks up incoming DNS-over-TLS queries on port 5553 and uses the nameservers defined in /etc/resolv.conf to resolve the query. This proxy path uses plain old DNS. A 10 second read timeout, 20 second write timeout and a 60 second idle timeout have been configured.

```
tls://.:5553 {

    tls cert.pem key.pem ca.pem

    timeouts {

        read 10s

        write 20s

        idle 60s

    }

    forward . /etc/resolv.conf
}
```

Start a DNS-over-HTTPS server that is similar to the previous example. Only the read timeout has been configured for 1 minute.

```
https://. {

    tls cert.pem key.pem ca.pem

    timeouts {

        read 1m

    }

    forward . /etc/resolv.conf
}
```

Start a standard TCP/UDP server on port 1053. A read and write timeout has been configured. The timeouts are only applied to the TCP side of the server.

```
.:1053 {

    timeouts {

        read 15s

                write 30s

    }

    forward . /etc/resolv.conf
}
```


coredns-tls

title: coredns-tls(7)

text:
# coredns-tls(7)

## NAME
tls - allows you to configure the server certificates for the TLS and gRPC servers.

## DESCRIPTION
CoreDNS supports queries that are encrypted using TLS (DNS over Transport Layer Security, RFC 7858) or are using gRPC (https://grpc.io/ ⟨https://grpc.io/⟩, not an IETF standard). Normally DNS traffic isn't encrypted at all (DNSSEC only signs resource records).

The tls "plugin" allows you to configure the cryptographic keys that are needed for both DNS-over-TLS and DNS-over-gRPC. If the tls plugin is omitted, then no encryption takes place.

The gRPC protobuffer is defined in pb/dns.proto. It defines the proto as a simple wrapper for the wire data of a DNS message.

## SYNTAX

```
tls CERT KEY [CA]
```

Parameter CA is optional. If not set, system CAs can be used to verify the client certificate

```
tls CERT KEY [CA] {

    client_auth nocert|request|require|verify_if_given|require_and_verify
}
```

If client_auth option is specified, it controls the client authentication policy. The option value corresponds to the ClientAuthType values of the Go tls package ⟨https://golang.org/pkg/crypto/tls/#ClientAuthType⟩: NoClientCert, RequestClientCert, RequireAnyClientCert, VerifyClientCertIfGiven, and RequireAndVerifyClientCert, respectively. The default is "nocert". Note that it makes no sense to specify parameter CA unless this option is set to verify_if_given or require_and_verify.

## EXAMPLES
Start a DNS-over-TLS server that picks up incoming DNS-over-TLS queries on port 5553 and uses the nameservers defined in /etc/resolv.conf to resolve the query. This proxy path uses plain old DNS.

```
tls://.:5553 {

    tls cert.pem key.pem ca.pem

    forward . /etc/resolv.conf
}
```

Start a DNS-over-gRPC server that is similar to the previous example, but using DNS-over-gRPC for incoming queries.

```
grpc://. {

    tls cert.pem key.pem ca.pem

    forward . /etc/resolv.conf
}
```

Only Knot DNS' kdig supports DNS-over-TLS queries, no command line client supports gRPC making debugging these transports harder than it should be.

## SEE ALSO
RFC 7858 and https://grpc.io ⟨https://grpc.io⟩.


coredns-trace

title: coredns-trace(7)

text:
# coredns-trace(7)

## NAME
trace - enables OpenTracing-based tracing of DNS requests as they go through the plugin chain.

## DESCRIPTION
With trace you enable OpenTracing of how a request flows through CoreDNS. Enable the debug plugin to get logs from the trace plugin.

## SYNTAX
The simplest form is just:

```
trace [ENDPOINT-TYPE] [ENDPOINT]
```

- ENDPOINT-TYPE is the type of tracing destination. Currently only zipkin and datadog are supported. Defaults to zipkin.

- ENDPOINT is the tracing destination, and defaults to localhost:9411. For Zipkin, if ENDPOINT does not begin with http, then it will be transformed to http://ENDPOINT/api/v1/spans.

With this form, all queries will be traced.

Additional features can be enabled with this syntax:

```
trace [ENDPOINT-TYPE] [ENDPOINT] {

    every AMOUNT

    service NAME

    client_server

    datadog_analytics_rate RATE
}
```

- every AMOUNT will only trace one query of each AMOUNT queries. For example, to trace 1 in every 100 queries, use AMOUNT of 100. The default is 1.

- service NAME allows you to specify the service name reported to the tracing server. Default is coredns.

- client_server will enable the ClientServerSameSpan OpenTracing feature.

- datadog_analytics_rate RATE will enable trace analytics ⟨https://docs.datadoghq.com/tracing/app_analytics⟩ on the traces sent from 0 to 1, 1 being every trace sent will be analyzed. This is a datadog only feature (ENDPOINT-TYPE needs to be datadog)

## ZIPKIN
You can run Zipkin on a Docker host like this:

```
docker run -d -p 9411:9411 openzipkin/zipkin
```

Note the zipkin provider does not support the v1 API since coredns 1.7.1.

## EXAMPLES
Use an alternative Zipkin address:

```
trace tracinghost:9253
```

or

```
. {

    trace zipkin tracinghost:9253
}
```

If for some reason you are using an API reverse proxy or something and need to remap the standard Zipkin URL you can do something like:

```
trace http://tracinghost:9411/zipkin/api/v1/spans
```

Using DataDog:

```
trace datadog localhost:8126
```

Trace one query every 10000 queries, rename the service, and enable same span:

```
trace tracinghost:9411 {

    every 10000

    service dnsproxy

    client_server
}
```

## SEE ALSO
See the debug plugin for more information about debug logging.


coredns-transfer

title: coredns-transfer(7)

text:
# coredns-transfer(7)

## NAME
transfer - perform (outgoing) zone transfers for other plugins.

## DESCRIPTION
This plugin answers zone transfers for authoritative plugins that implement transfer.Transferer.

transfer answers full zone transfer (AXFR) requests and incremental zone transfer (IXFR) requests with AXFR fallback if the zone has changed.

When a plugin wants to notify it's secondaries it will call back into the transfer plugin.

The following plugins implement zone transfers using this plugin: file, auto, secondary, and kubernetes. See transfer.go for implementation details if you are a plugin author that wants to use this plugin.

## SYNTAX

```
transfer [ZONE...] {

  to ADDRESS...
}
```

- ZONE The zones transfer will answer zone transfer requests for. If left blank, the zones are inherited from the enclosing server block. To answer zone transfers for a given zone, there must be another plugin in the same server block that serves the same zone, and implements transfer.Transferer.

- to ADDRESS... The hosts transfer will transfer to. Use * to permit transfers to all addresses. ADDRESS must be denoted in CIDR notation (e.g., 127.0.0.1/32) or just as plain addresses. to may be specified multiple times.

## EXAMPLES
See the specific plugins using this plugin for examples on it's usage.


coredns-tsig

title: coredns-tsig(7)

text:
# coredns-tsig(7)

## NAME
tsig - validate TSIG requests and sign responses.

## DESCRIPTION
With tsig, you can define a set of TSIG secret keys for validating incoming TSIG requests and signing responses. It can also require TSIG for certain query types, refusing requests that do not comply.

## SYNTAX

```
tsig [ZONE...] {

  secret NAME KEY

  secrets FILE

  require [QTYPE...]
}
```

- ZONE - the zones tsig will TSIG. By default, the zones from the server block are used.

- secret NAME KEY - specifies a TSIG secret for NAME with KEY. Use this option more than once to define multiple secrets. Secrets are global to the server instance, not just for the enclosing ZONE.

- secrets FILE - same as secret, but load the secrets from a file. The file may define any number

of unique keys, each in the following named.conf format:

```
 key "example." {

     secret "X28hl0BOfAL5G0jsmJWSacrwn7YRm2f6U5brnzwWEus=";

 };
```

Each key may also specify an algorithm e.g. algorithm hmac-sha256;, but this is currently ignored by the plugin.

–

require QTYPE... - the query types that must be TSIG'd. Requests of the specified types will be REFUSED if they are not signed.require all will require requests of all types to be signed. require none will not require requests any types to be signed. Default behavior is to not require.

## EXAMPLES
Require TSIG signed transactions for transfer requests to example.zone.

```
example.zone {

  tsig {

    secret example.zone.key. NoTCJU+DMqFWywaPyxSijrDEA/eC3nK0xi3AMEZuPVk=

    require AXFR IXFR

  }

  transfer {

    to *

  }
}
```

Require TSIG signed transactions for all requests to auth.zone.

```
auth.zone {

  tsig {

    secret auth.zone.key. NoTCJU+DMqFWywaPyxSijrDEA/eC3nK0xi3AMEZuPVk=

    require all

  }

  forward . 10.1.0.2
}
```

## BUGS

### ZONE TRANSFER NOTIFIES
With the transfer plugin, zone transfer notifications from CoreDNS are not TSIG signed.

### SPECIAL CONSIDERATIONS FOR FORWARDING SERVERS (RFC 8945 5.5)
https://datatracker.ietf.org/doc/html/rfc8945#section-5.5 ⟨https://datatracker.ietf.org/doc/html/rfc8945#section-5.5⟩

CoreDNS does not implement this section as follows ...

•

RFC requirement: > If the name on the TSIG is not of a secret that the server shares with the originator, the server MUST forward the message unchanged including the TSIG.

CoreDNS behavior: If ths zone of the request matches the tsig plugin zones, then the TSIG record is always stripped. But even when the tsig plugin is not involved, the forward plugin may alter the message with compression, which would cause validation failure at the destination.

•

RFC requirement: > If the TSIG passes all checks, the forwarding server MUST, if possible, include a TSIG of its own to the destination or the next forwarder.

CoreDNS behavior: If ths zone of the request matches the tsig plugin zones, forward plugin will proxy the request upstream without TSIG.

•

RFC requirement: > If no transaction security is available to the destination and the message is a query, and if the corresponding response has the AD flag (see RFC4035) set, the forwarder MUST clear the AD flag before adding the TSIG to the response and returning the result to the system from which it received the query.

CoreDNS behavior: The AD flag is not cleared.


coredns-view

title: coredns-view(7)

text:
# coredns-view(7)

## NAME
view - defines conditions that must be met for a DNS request to be routed to the server block.

## DESCRIPTION
view defines an expression that must evaluate to true for a DNS request to be routed to the server block. This enables advanced server block routing functions such as split dns.

## SYNTAX

```
view NAME {

  expr EXPRESSION
}
```

- view NAME - The name of the view used by metrics and exported as metadata for requests that match the view's expression

- expr EXPRESSION - CoreDNS will only route incoming queries to the enclosing server block if the EXPRESSION evaluates to true. See the Expressions section for available variables and functions. If multiple instances of view are defined, all EXPRESSION must evaluate to true for CoreDNS will only route incoming queries to the enclosing server block.

For expression syntax and examples, see the Expressions and Examples sections.

## EXAMPLES
Implement CIDR based split DNS routing. This will return a different answer for test. depending on client's IP address. It returns ... * test. 3600 IN A 1.1.1.1, for queries with a source address in 127.0.0.0/24 * test. 3600 IN A 2.2.2.2, for queries with a source address in 192.168.0.0/16 * test. 3600 IN A 3.3.3.3, for all others

```
. {

  view example1 {

    expr incidr(client_ip(), '127.0.0.0/24')

  }

  hosts {

    1.1.1.1 test

  }
}
. {

  view example2 {

    expr incidr(client_ip(), '192.168.0.0/16')

  }

  hosts {

    2.2.2.2 test

  }
}
. {

  hosts {

    3.3.3.3 test

  }
}
```

Send all A and AAAA requests to 10.0.0.6, and all other requests to 10.0.0.1.

```
. {

  view example {

    expr type() in ['A', 'AAAA']

  }

  forward . 10.0.0.6
}
. {

  forward . 10.0.0.1
}
```

Send all requests for abc.*.example.com (where * can be any number of labels), to 10.0.0.2, and all other requests to 10.0.0.1. Note that the regex pattern is enclosed in single quotes, and backslashes are escaped with backslashes.

```
. {

  view example {

    expr name() matches '^abc\\..*\\.example\\.com\\.$'

  }

  forward . 10.0.0.2
}
. {

  forward . 10.0.0.1
}
```

## EXPRESSIONS
To evaluate expressions, view uses the antonmedv/expr package (https://github.com/antonmedv/expr ⟨https://github.com/antonmedv/expr⟩). For example, an expression could look like: (type() == 'A' && name() == 'example.com') || client_ip() == '1.2.3.4'.

All expressions should be written to evaluate to a boolean value.

See https://github.com/antonmedv/expr/blob/master/docs/Language-Definition.md ⟨https://github.com/antonmedv/expr/blob/master/docs/Language-Definition.md⟩ as a detailed reference for valid syntax.

### AVAILABLE EXPRESSION FUNCTIONS
In the context of the view plugin, expressions can reference DNS query information by using utility functions defined below.

### DNS QUERY FUNCTIONS

- bufsize() int: the EDNS0 buffer size advertised in the query

- class() string: class of the request (IN, CH, ...)

- client_ip() string: client's IP address, for IPv6 addresses these are enclosed in brackets: [::1]

- do() bool: the EDNS0 DO (DNSSEC OK) bit set in the query

- id() int: query ID

- name() string: name of the request (the domain name requested)

- opcode() int: query OPCODE

- port() string: client's port

- proto() string: protocol used (tcp or udp)

- server_ip() string: server's IP address; for IPv6 addresses these are enclosed in brackets: [::1]

- server_port() string : client's port

- size() int: request size in bytes

- type() string: type of the request (A, AAAA, TXT, ...)

### UTILITY FUNCTIONS

- incidr(ip string, cidr string) bool: returns true if ip is within cidr

- metadata(label string) - returns the value for the metadata matching label

## METADATA
The view plugin will publish the following metadata, if the metadata plugin is also enabled:

•

view/name: the name of the view handling the current request


coredns-whoami

title: coredns-whoami(7)

text:
# coredns-whoami(7)

## NAME
whoami - returns your resolver's local IP address, port and transport.

## DESCRIPTION
The whoami plugin is not really that useful, but can be used for having a simple (fast) endpoint to test clients against. When whoami returns a response it will have your client's IP address in the additional section as either an A or AAAA record.

The reply always has an empty answer section. The port and transport are included in the additional section as a SRV record, transport can be "tcp" or "udp".

```
._<transport>.qname. 0 IN SRV 0 0 <port> .
```

The whoami plugin will respond to every A or AAAA query, regardless of the query name.

If CoreDNS can't find a Corefile on startup this is the default plugin that gets loaded. As such it can be used to check that CoreDNS is responding to queries. Other than that this plugin is of limited use in production.

## SYNTAX

```
whoami
```

## EXAMPLES
Start a server on the default port and load the whoami plugin.

```
example.org {

    whoami
}
```

When queried for "example.org A", CoreDNS will respond with:

```
;; QUESTION SECTION:
;example.org.   IN       A
;; ADDITIONAL SECTION:
example.org.            0       IN      A       10.240.0.1
_udp.example.org.       0       IN      SRV     0 0 40212
```

## SEE ALSO
Read the blog post ⟨https://coredns.io/2017/03/01/how-to-add-plugins-to-coredns/⟩ on how this plugin is built, or explore the source code ⟨https://github.com/coredns/coredns/blob/master/plugin/whoami/⟩.


coredns-acl

title: coredns-acl(7)

text:
# coredns-acl(7)

## NAME
acl - enforces access control policies on source ip and prevents unauthorized access to DNS servers.

## DESCRIPTION
With acl enabled, users are able to block or filter suspicious DNS queries by configuring IP filter rule sets, i.e. allowing authorized queries to recurse or blocking unauthorized queries.

This plugin can be used multiple times per Server Block.

## SYNTAX

```
acl [ZONES...] {

    ACTION [type QTYPE...] [net SOURCE...]
}
```

- ZONES zones it should be authoritative for. If empty, the zones from the configuration block are used.

- ACTION (allow, block, or filter) defines the way to deal with DNS queries matched by this rule. The default action is allow, which means a DNS query not matched by any rules will be allowed to recurse. The difference between block and filter is that block returns status code of REFUSED while filter returns an empty set NOERROR

- QTYPE is the query type to match for the requests to be allowed or blocked. Common resource record types are supported. * stands for all record types. The default behavior for an omitted type QTYPE... is to match all kinds of DNS queries (same as type *).

- SOURCE is the source IP address to match for the requests to be allowed or blocked. Typical CIDR notation and single IP address are supported. * stands for all possible source IP addresses.

## EXAMPLES
To demonstrate the usage of plugin acl, here we provide some typical examples.

Block all DNS queries with record type A from 192.168.0.0/16：

```
. {

    acl {

        block type A net 192.168.0.0/16

    }
}
```

Filter all DNS queries with record type A from 192.168.0.0/16：

```
. {

    acl {

        filter type A net 192.168.0.0/16

    }
}
```

Block all DNS queries from 192.168.0.0/16 except for 192.168.1.0/24:

```
. {

    acl {

        allow net 192.168.1.0/24

        block net 192.168.0.0/16

    }
}
```

Allow only DNS queries from 192.168.0.0/24 and 192.168.1.0/24:

```
. {

    acl {

        allow net 192.168.0.0/24 192.168.1.0/24

        block

    }
}
```

Block all DNS queries from 192.168.1.0/24 towards a.example.org:

```
example.org {

    acl a.example.org {

        block net 192.168.1.0/24

    }
}
```

## METRICS
If monitoring is enabled (via the prometheus plugin) then the following metrics are exported:

- coredns_acl_blocked_requests_total{server, zone} - counter of DNS requests being blocked.

- coredns_acl_allowed_requests_total{server} - counter of DNS requests being allowed.

The server and zone labels are explained in the metrics plugin documentation.


coredns-any

title: coredns-any(7)

text:
# coredns-any(7)

## NAME
any - gives a minimal response to ANY queries.

## DESCRIPTION
any basically blocks ANY queries by responding to them with a short HINFO reply. See RFC 8482 ⟨https://tools.ietf.org/html/rfc8482⟩ for details.

## SYNTAX

```
any
```

## EXAMPLES

```
example.org {

    whoami

    any
}
```

A dig +nocmd ANY example.org +noall +answer now returns:

```
example.org.  8482    IN    HINFO    "ANY obsoleted" "See RFC 8482"
```

## SEE ALSO
RFC 8482 ⟨https://tools.ietf.org/html/rfc8482⟩.


coredns-auto

title: coredns-auto(7)

text:
# coredns-auto(7)

## NAME
auto - enables serving zone data from an RFC 1035-style master file, which is automatically picked up from disk.

## DESCRIPTION
The auto plugin is used for an "old-style" DNS server. It serves from a preloaded file that exists on disk. If the zone file contains signatures (i.e. is signed, i.e. using DNSSEC) correct DNSSEC answers are returned. Only NSEC is supported! If you use this setup you are responsible for re-signing the zonefile. New or changed zones are automatically picked up from disk only when SOA's serial changes. If the zones are not updated via a zone transfer, the serial must be manually changed.

## SYNTAX

```
auto [ZONES...] {

    directory DIR [REGEXP ORIGIN_TEMPLATE]

    reload DURATION
}
```

ZONES zones it should be authoritative for. If empty, the zones from the configuration block are used.

- directory loads zones from the specified DIR. If a file name matches REGEXP it will be used to extract the origin. ORIGIN_TEMPLATE will be used as a template for the origin. Strings like {<number>} are replaced with the respective matches in the file name, e.g. {1} is the first match, {2} is the second. The default is: db.(.*) {1} i.e. from a file with the name db.example.com, the extracted origin will be example.com.

- reload interval to perform reloads of zones if SOA version changes and zonefiles. It specifies how often CoreDNS should scan the directory to watch for file removal and addition. Default is one minute. Value of 0 means to not scan for changes and reload. eg. 30s checks zonefile every 30 seconds and reloads zone when serial changes.

For enabling zone transfers look at the transfer plugin.

All directives from the file plugin are supported. Note that auto will load all zones found, even though the directive might only receive queries for a specific zone. I.e:

```
. {

    auto example.org {

        directory /etc/coredns/zones

    }
}
```

Will happily pick up a zone for example.COM, except it will never be queried, because the auto directive only is authoritative for example.ORG.

## EXAMPLES
Load org domains from /etc/coredns/zones/org and allow transfers to the internet, but send notifies to 10.240.1.1

```
org {

    auto {

        directory /etc/coredns/zones/org

    }

    transfer {

        to *

        to 10.240.1.1

    }
}
```

Load org domains from /etc/coredns/zones/org and looks for file names as www.db.example.org, where example.org is the origin. Scan every 45 seconds.

```
org {

    auto {

        directory /etc/coredns/zones/org www\.db\.(.*) {1}

        reload 45s

    }
}
```

## ALSO
Use the root plugin to help you specify the location of the zone files. See the transfer plugin to enable outgoing zone transfers.


coredns-autopath

title: coredns-autopath(7)

text:
# coredns-autopath(7)

## NAME
autopath - allows for server-side search path completion.

## DESCRIPTION
If the autopath plugin sees a query that matches the first element of the configured search path, it will follow the chain of search path elements and return the first reply that is not NXDOMAIN. On any failures, the original reply is returned. Because autopath returns a reply for a name that wasn't the original question, it will add a CNAME that points from the original name (with the search path element in it) to the name of this answer.

Note: There are several known issues, see the "Bugs" section below.

## SYNTAX

```
autopath [ZONE...] RESOLV-CONF
```

- ZONES zones autopath should be authoritative for.

- RESOLV-CONF points to a resolv.conf like file or uses a special syntax to point to another plugin. For instance @kubernetes, will call out to the kubernetes plugin (for each query) to retrieve the search list it should use.

If a plugin implements the AutoPather interface then it can be used by autopath.

## METRICS
If monitoring is enabled (via the prometheus plugin) then the following metric is exported:

•

coredns_autopath_success_total{server} - counter of successfully autopath-ed queries.

The server label is explained in the metrics plugin documentation.

## EXAMPLES

```
autopath my-resolv.conf
```

Use my-resolv.conf as the file to get the search path from. This file only needs to have one line: search domain1 domain2 ...

```
autopath @kubernetes
```

Use the search path dynamically retrieved from the kubernetes plugin.

## BUGS
In Kubernetes, autopath can derive the wrong namespace of a client Pod (and therefore wrong search path) in the following case. To properly build the search path of a client autopath needs to know the namespace of the a Pod making a DNS request. To do this, it relies on the kubernetes plugin's Pod cache to resolve the client's IP address to a Pod. The Pod cache is maintained by an API watch on Pods. When Pod IP assignments change, the Kubernetes API notifies CoreDNS via the API watch. However, that notification is not instantaneous. In the case that a Pod is deleted, and it's IP is immediately provisioned to a Pod in another namespace, and that new Pod make a DNS lookup before the API watch can notify CoreDNS of the change, autopath will resolve the IP to the previous Pod's namespace.

In Kubernetes, autopath is not compatible with Pods running from Windows nodes.

If the server side search ultimately results in a negative answer (e.g. NXDOMAIN), then the client will fruitlessly search all paths manually, thus negating the autopath optimization.


coredns-azure

title: coredns-azure(7)

text:
# coredns-azure(7)

## NAME
azure - enables serving zone data from Microsoft Azure DNS service.

## DESCRIPTION
The azure plugin is useful for serving zones from Microsoft Azure DNS. The azure plugin supports all the DNS records supported by Azure, viz. A, AAAA, CNAME, MX, NS, PTR, SOA, SRV, and TXT record types. NS record type is not supported by azure private DNS.

## SYNTAX

```
azure RESOURCE_GROUP:ZONE... {

    tenant TENANT_ID

    client CLIENT_ID

    secret CLIENT_SECRET

    subscription SUBSCRIPTION_ID

    environment ENVIRONMENT

    fallthrough [ZONES...]

    access private
}
```

- RESOURCE_GROUP:ZONE is the resource group to which the hosted zones belongs on Azure, and ZONE the zone that contains data.

- CLIENT_ID and CLIENT_SECRET are the credentials for Azure, and tenant specifies the TENANT_ID to be used. SUBSCRIPTION_ID is the subscription ID. All of these are needed to access the data in Azure.

- environment specifies the Azure ENVIRONMENT.

- fallthrough If zone matches and no record can be generated, pass request to the next plugin. If ZONES is omitted, then fallthrough happens for all zones for which the plugin is authoritative.

- access specifies if the zone is public or private. Default is public.

## EXAMPLES
Enable the azure plugin with Azure credentials for private zones example.org, example.private:

```
example.org {

    azure resource_group_foo:example.org resource_group_foo:example.private {

      tenant 123abc-123abc-123abc-123abc

      client 123abc-123abc-123abc-234xyz

      subscription 123abc-123abc-123abc-563abc

      secret mysecret

      access private

    }
}
```

## SEE ALSO
The Azure DNS Overview ⟨https://docs.microsoft.com/en-us/azure/dns/dns-overview⟩.


coredns-bind

title: coredns-bind(7)

text:
# coredns-bind(7)

## NAME
bind - overrides the host to which the server should bind.

## DESCRIPTION
Normally, the listener binds to the wildcard host. However, you may want the listener to bind to another IP instead.

If several addresses are provided, a listener will be open on each of the IP provided.

Each address has to be an IP or name of one of the interfaces of the host. Bind by interface name, binds to the IPs on that interface at the time of startup or reload (reload will happen with a SIGHUP or if the config file changes).

If the given argument is an interface name, and that interface has serveral IP addresses, CoreDNS will listen on all of the interface IP addresses (including IPv4 and IPv6).

## SYNTAX

```
bind ADDRESS  ...
```

ADDRESS is an IP address to bind to. When several addresses are provided a listener will be opened on each of the addresses.

## EXAMPLES
To make your socket accessible only to that machine, bind to IP 127.0.0.1 (localhost):

```
. {

    bind 127.0.0.1
}
```

To allow processing DNS requests only local host on both IPv4 and IPv6 stacks, use the syntax:

```
. {

    bind 127.0.0.1 ::1
}
```

If the configuration comes up with several bind plugins, all addresses are consolidated together: The following sample is equivalent to the preceding:

```
. {

    bind 127.0.0.1

    bind ::1
}
```

The following server block, binds on localhost with its interface name (both "127.0.0.1" and "::1"):

```
. {

    bind lo
}
```

## BUGS
When defining more than one server block, take care not to bind more than one server to the same address and port. Doing so will result in unpredictable behavior (requests may be randomly served by either server). Keep in mind that without the bind plugin, a server will bind to all interfaces, and this will collide with another server if it's using bind to listen to an interface on the same port. For example, the following creates two servers that both listen on 127.0.0.1:53, which would result in unpredictable behavior for queries in a.bad.example.com:

```
a.bad.example.com {

    bind 127.0.0.1

    forward . 1.2.3.4
}
bad.example.com {

    forward . 5.6.7.8
}
```


coredns-bufsize

title: coredns-bufsize(7)

text:
# coredns-bufsize(7)

## NAME
bufsize - sizes EDNS0 buffer size to prevent IP fragmentation.

## DESCRIPTION
bufsize limits a requester's UDP payload size. It prevents IP fragmentation, mitigating certain DNS vulnerabilities.

## SYNTAX

```
bufsize [SIZE]
```

[SIZE] is an int value for setting the buffer size. The default value is 512, and the value must be within 512 - 4096. Only one argument is acceptable, and it covers both IPv4 and IPv6.

## EXAMPLES
Enable limiting the buffer size of outgoing query to the resolver (172.31.0.10):

```
. {

    bufsize 512

    forward . 172.31.0.10

    log
}
```

Enable limiting the buffer size as an authoritative nameserver:

```
. {

    bufsize 512

    file db.example.org

    log
}
```

## CONSIDERATIONS

- Setting 1232 bytes to bufsize may avoid fragmentation on the majority of networks in use today, but it depends on the MTU of the physical network links.

- For now, if a client does not use EDNS, this plugin adds OPT RR.


coredns-cache

title: coredns-cache(7)

text:
# coredns-cache(7)

## NAME
cache - enables a frontend cache.

## DESCRIPTION
With cache enabled, all records except zone transfers and metadata records will be cached for up to 3600s. Caching is mostly useful in a scenario when fetching data from the backend (upstream, database, etc.) is expensive.

Cache will change the query to enable DNSSEC (DNSSEC OK; DO) if it passes through the plugin. If the client didn't request any DNSSEC (records), these are filtered out when replying.

This plugin can only be used once per Server Block.

## SYNTAX

```
cache [TTL] [ZONES...]
```

- TTL max TTL in seconds. If not specified, the maximum TTL will be used, which is 3600 for NOERROR responses and 1800 for denial of existence ones. Setting a TTL of 300: cache 300 would cache records up to 300 seconds.

- ZONES zones it should cache for. If empty, the zones from the configuration block are used.

Each element in the cache is cached according to its TTL (with TTL as the max). A cache is divided into 256 shards, each holding up to 39 items by default - for a total size of 256 * 39 = 9984 items.

If you want more control:

```
cache [TTL] [ZONES...] {

    success CAPACITY [TTL] [MINTTL]

    denial CAPACITY [TTL] [MINTTL]

    prefetch AMOUNT [[DURATION] [PERCENTAGE%]]

    serve_stale [DURATION]
}
```

- TTL and ZONES as above.

- success, override the settings for caching successful responses. CAPACITY indicates the maximum number of packets we cache before we start evicting (randomly). TTL overrides the cache maximum TTL. MINTTL overrides the cache minimum TTL (default 5), which can be useful to limit queries to the backend.

- denial, override the settings for caching denial of existence responses. CAPACITY indicates the maximum number of packets we cache before we start evicting (LRU). TTL overrides the cache maximum TTL. MINTTL overrides the cache minimum TTL (default 5), which can be useful to limit queries to the backend. There is a third category (error) but those responses are never cached.

- prefetch will prefetch popular items when they are about to be expunged from the cache. Popular means AMOUNT queries have been seen with no gaps of DURATION or more between them. DURATION defaults to 1m. Prefetching will happen when the TTL drops below PERCENTAGE, which defaults to 10%, or latest 1 second before TTL expiration. Values should be in the range [10%, 90%]. Note the percent sign is mandatory. PERCENTAGE is treated as an int.

- serve_stale, when serve_stale is set, cache always will serve an expired entry to a client if there is one available. When this happens, cache will attempt to refresh the cache entry after sending the expired cache entry to the client. The responses have a TTL of 0. DURATION is how far back to consider stale responses as fresh. The default duration is 1h.

## CAPACITY AND EVICTION
If CAPACITY is not specified, the default cache size is 9984 per cache. The minimum allowed cache size is 1024. If CAPACITY is specified, the actual cache size used will be rounded down to the nearest number divisible by 256 (so all shards are equal in size).

Eviction is done per shard. In effect, when a shard reaches capacity, items are evicted from that shard. Since shards don't fill up perfectly evenly, evictions will occur before the entire cache reaches full capacity. Each shard capacity is equal to the total cache size / number of shards (256). Eviction is random, not TTL based. Entries with 0 TTL will remain in the cache until randomly evicted when the shard reaches capacity.

## METRICS
If monitoring is enabled (via the prometheus plugin) then the following metrics are exported:

- coredns_cache_entries{server, type} - Total elements in the cache by cache type.

- coredns_cache_hits_total{server, type} - Counter of cache hits by cache type.

- coredns_cache_misses_total{server} - Counter of cache misses.

- coredns_cache_prefetch_total{server} - Counter of times the cache has prefetched a cached item.

- coredns_cache_drops_total{server} - Counter of responses excluded from the cache due to request/response question name mismatch.

- coredns_cache_served_stale_total{server} - Counter of requests served from stale cache entries.

Cache types are either "denial" or "success". Server is the server handling the request, see the prometheus plugin for documentation.

## EXAMPLES
Enable caching for all zones, but cap everything to a TTL of 10 seconds:

```
. {

    cache 10

    whoami
}
```

Proxy to Google Public DNS and only cache responses for example.org (or below).

```
. {

    forward . 8.8.8.8:53

    cache example.org
}
```

Enable caching for example.org, keep a positive cache size of 5000 and a negative cache size of 2500:

```
example.org {

    cache {

        success 5000

        denial 2500

    }
}
```


coredns-cancel

title: coredns-cancel(7)

text:
# coredns-cancel(7)

## NAME
cancel - cancels a request's context after 5001 milliseconds.

## DESCRIPTION
The cancel plugin creates a canceling context for each request. It adds a timeout that gets triggered after 5001 milliseconds.

The 5001 number was chosen because the default timeout for DNS clients is 5 seconds, after that they give up.

A plugin interested in the cancellation status should call plugin.Done() on the context. If the context was canceled due to a timeout the plugin should not write anything back to the client and return a value indicating CoreDNS should not either; a zero return value should suffice for that.

## SYNTAX

```
cancel [TIMEOUT]
```

•

TIMEOUT allows setting a custom timeout. The default timeout is 5001 milliseconds (5001 ms)

## EXAMPLES

```
example.org {

    cancel

    whoami
}
```

Or with a custom timeout:

```
example.org {

    cancel 1s

    whoami
}
```

## SEE ALSO
The Go documentation for the context package.


coredns-chaos

title: coredns-chaos(7)

text:
# coredns-chaos(7)

## NAME
chaos - allows for responding to TXT queries in the CH class.

## DESCRIPTION
This is useful for retrieving version or author information from the server by querying a TXT record for a special domain name in the CH class.

## SYNTAX

```
chaos [VERSION] [AUTHORS...]
```

- VERSION is the version to return. Defaults to CoreDNS-<version>, if not set.

- AUTHORS is what authors to return. This defaults to all GitHub handles in the OWNERS files.

Note that you have to make sure that this plugin will get actual queries for the following zones: version.bind, version.server, authors.bind, hostname.bind and id.server.

## EXAMPLES
Specify all the zones in full.

```
version.bind version.server authors.bind hostname.bind id.server {

    chaos CoreDNS-001 info@coredns.io
}
```

Or just default to .:

```
.  {

    chaos CoreDNS-001 info@coredns.io
}
```

And test with dig:

```
% dig @localhost CH TXT version.bind
...
;; ANSWER SECTION:
version.bind.        0    CH    TXT    "CoreDNS-001"
...
```


coredns-clouddns

title: coredns-clouddns(7)

text:
# coredns-clouddns(7)

## NAME
clouddns - enables serving zone data from GCP Cloud DNS.

## DESCRIPTION
The clouddns plugin is useful for serving zones from resource record sets in GCP Cloud DNS. This plugin supports all Google Cloud DNS records ⟨https://cloud.google.com/dns/docs/overview#supported_dns_record_types⟩. This plugin can be used when CoreDNS is deployed on GCP or elsewhere. Note that this plugin accesses the resource records through the Google Cloud API. For records in a privately hosted zone, it is not necessary to place CoreDNS and this plugin in the associated VPC network. In fact the private hosted zone could be created without any associated VPC and this plugin could still access the resource records under the hosted zone.

## SYNTAX

```
clouddns [ZONE:PROJECT_ID:HOSTED_ZONE_NAME...] {

    credentials [FILENAME]

    fallthrough [ZONES...]
}
```

- ZONE the name of the domain to be accessed. When there are multiple zones with overlapping domains (private vs. public hosted zone), CoreDNS does the lookup in the given order here. Therefore, for a non-existing resource record, SOA response will be from the rightmost zone.

- PROJECT_ID the project ID of the Google Cloud project.

- HOSTED_ZONE_NAME the name of the hosted zone that contains the resource record sets to be accessed.

- credentials is used for reading the credential file from FILENAME (normally a .json file).

- fallthrough If zone matches and no record can be generated, pass request to the next plugin. If [ZONES...] is omitted, then fallthrough happens for all zones for which the plugin is authoritative. If specific zones are listed (for example in-addr.arpa and ip6.arpa), then only queries for those zones will be subject to fallthrough.

## EXAMPLES
Enable clouddns with implicit GCP credentials and resolve CNAMEs via 10.0.0.1:

```
example.org {

    clouddns example.org.:gcp-example-project:example-zone

    forward . 10.0.0.1
}
```

Enable clouddns with fallthrough:

```
example.org {

    clouddns example.org.:gcp-example-project:example-zone example.com.:gcp-example-project:example-zone-2 {

        fallthrough example.gov.

    }
}
```

Enable clouddns with multiple hosted zones with the same domain:

```
. {

    clouddns example.org.:gcp-example-project:example-zone example.com.:gcp-example-project:other-example-zone
}
```


coredns-debug

title: coredns-debug(7)

text:
# coredns-debug(7)

## NAME
debug - disables the automatic recovery upon a crash so that you'll get a nice stack trace.

## DESCRIPTION
Normally CoreDNS will recover from panics; using debug inhibits this. The main use of debug is to help in testing. A side effect of using debug is that log.Debug and log.Debugf messages will be printed to standard output.

Note that the errors plugin (if loaded) will also set a recover, negating this setting.

Enabling this plugin is process-wide: enabling debug in at least one server block enables debug mode globally.

## SYNTAX

```
debug
```

Some plugins will send debug log DNS messages. This is done in the following format:

```
debug: 000000 00 0a 01 00 00 01 00 00 00 00 00 01 07 65 78 61
debug: 000010 6d 70 6c 65 05 6c 6f 63 61 6c 00 00 01 00 01 00
debug: 000020 00 29 10 00 00 00 80 00 00 00
debug: 00002a
```

Using text2pcap (part of Wireshark), this can be converted back to binary, with the following command line: text2pcap -i 17 -u 53,53, where 17 is the protocol (UDP) and 53 are the ports. These ports allow Wireshark to detect these packets as DNS messages.

Each plugin can decide whether to dump messages to aid in debugging.

## EXAMPLES
Disable the ability to recover from crashes and show debug logging:

```
. {

    debug
}
```

## SEE ALSO
https://www.wireshark.org/docs/man-pages/text2pcap.html ⟨https://www.wireshark.org/docs/man-pages/text2pcap.html⟩.


title: coredns-dns64(7)

text:
# coredns-dns64(7)

## NAME
dns64 - enables DNS64 IPv6 transition mechanism.

## DESCRIPTION
The dns64 plugin will when asked for a domain's AAAA records, but only finds A records, synthesizes the AAAA records from the A records.

The synthesis is only performed if the query came in via IPv6.

This translation is for IPv6-only networks that have NAT64 ⟨https://en.wikipedia.org/wiki/NAT64⟩.

## SYNTAX

```
dns64 [PREFIX]
```

•

PREFIX defines a custom prefix instead of the default 64:ff9b::/96.

Or use this slightly longer form with more options:

```
dns64 [PREFIX] {

    [translate_all]

    prefix PREFIX
}
```

- prefix specifies any local IPv6 prefix to use, instead of the well known prefix (64:ff9b::/96)

- translate_all translates all queries, including responses that have AAAA results.

## EXAMPLES
Translate with the default well known prefix. Applies to all queries (if they came in over IPv6).

```
. {

    dns64
}
```

Use a custom prefix.

```
. {

    dns64 64:1337::/96
}
```

Or

```
. {

    dns64 {

        prefix 64:1337::/96

    }
}
```

Enable translation even if an existing AAAA record is present.

```
. {

    dns64 {

        translate_all

    }
}
```

## METRICS
If monitoring is enabled (via the prometheus plugin) then the following metrics are exported:

•

coredns_dns64_requests_translated_total{server} - counter of DNS requests translated

The server label is explained in the prometheus plugin documentation.

## BUGS
Not all features required by DNS64 are implemented, only basic AAAA synthesis.

- Support "mapping of separate IPv4 ranges to separate IPv6 prefixes"

- Resolve PTR records

- Make resolver DNSSEC aware. See: RFC 6147 Section 3 ⟨https://tools.ietf.org/html/rfc6147#section-3⟩

## SEE ALSO
See RFC 6147 ⟨https://tools.ietf.org/html/rfc6147⟩ for more information on the DNS64 mechanism.