coredns-dnssec

title: coredns-dnssec(7)

text:
# coredns-dnssec(7)

## NAME
dnssec - enables on-the-fly DNSSEC signing of served data.

## DESCRIPTION
With dnssec, any reply that doesn't (or can't) do DNSSEC will get signed on the fly. Authenticated denial of existence is implemented with NSEC black lies. Using ECDSA as an algorithm is preferred as this leads to smaller signatures (compared to RSA). NSEC3 is not supported.

This plugin can only be used once per Server Block.

## SYNTAX

```
dnssec [ZONES... ] {

    key file KEY...

    cache_capacity CAPACITY
}
```

The signing behavior depends on the keys specified. If multiple keys are specified of which there is at least one key with the SEP bit set and at least one key with the SEP bit unset, signing will happen in split ZSK/KSK mode. DNSKEY records will be signed with all keys that have the SEP bit set. All other records will be signed with all keys that do not have the SEP bit set.

In any other case, each specified key will be treated as a CSK (common signing key), forgoing the ZSK/KSK split. All signing operations are done online. Authenticated denial of existence is implemented with NSEC black lies. Using ECDSA as an algorithm is preferred as this leads to smaller signatures (compared to RSA). NSEC3 is not supported.

If multiple dnssec plugins are specified in the same zone, the last one specified will be used (See bugs ⟨#bugs⟩).

- ZONES zones that should be signed. If empty, the zones from the configuration block are used.

- key file indicates that KEY file(s) should be read from disk. When multiple keys are specified, RRsets will be signed with all keys. Generating a key can be done with dnssec-keygen: dnssec-keygen -a ECDSAP256SHA256 <zonename>. A key created for zone A can be safely used for zone B. The name of the key file can be specified in one of the following formats

–

basename of the generated key Kexample.org+013+45330

–

generated public key Kexample.org+013+45330.key

–

generated private key Kexample.org+013+45330.private

•

cache_capacity indicates the capacity of the cache. The dnssec plugin uses a cache to store RRSIGs. The default for CAPACITY is 10000.

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

- coredns_dnssec_cache_entries{server, type} - total elements in the cache, type is "signature".

- coredns_dnssec_cache_hits_total{server} - Counter of cache hits.

- coredns_dnssec_cache_misses_total{server} - Counter of cache misses.

The label server indicated the server handling the request, see the metrics plugin for details.

## EXAMPLES
Sign responses for example.org with the key "Kexample.org.+013+45330.key".

```
example.org {

    dnssec {

        key file Kexample.org.+013+45330

    }

    whoami
}
```

Sign responses for a kubernetes zone with the key "Kcluster.local+013+45129.key".

```
cluster.local {

    kubernetes

    dnssec {

      key file Kcluster.local+013+45129

    }
}
```


coredns-dnstap

title: coredns-dnstap(7)

text:
# coredns-dnstap(7)

## NAME
dnstap - enables logging to dnstap.

## DESCRIPTION
dnstap is a flexible, structured binary log format for DNS software; see https://dnstap.info ⟨https://dnstap.info⟩. With this plugin you make CoreDNS output dnstap logging.

Every message is sent to the socket as soon as it comes in, the dnstap plugin has a buffer of 10000 messages, above that number dnstap messages will be dropped (this is logged).

## SYNTAX

```
dnstap SOCKET [full]
```

- SOCKET is the socket (path) supplied to the dnstap command line tool.

- full to include the wire-format DNS message.

## EXAMPLES
Log information about client requests and responses to /tmp/dnstap.sock.

```
dnstap /tmp/dnstap.sock
```

Log information including the wire-format DNS message about client requests and responses to /tmp/dnstap.sock.

```
dnstap unix:///tmp/dnstap.sock full
```

Log to a remote endpoint.

```
dnstap tcp://127.0.0.1:6000 full
```

## COMMAND LINE TOOL
Dnstap has a command line tool that can be used to inspect the logging. The tool can be found at Github: https://github.com/dnstap/golang-dnstap ⟨https://github.com/dnstap/golang-dnstap⟩. It's written in Go.

The following command listens on the given socket and decodes messages to stdout.

```
$ dnstap -u /tmp/dnstap.sock
```

The following command listens on the given socket and saves message payloads to a binary dnstap-format log file.

```
$ dnstap -u /tmp/dnstap.sock -w /tmp/test.dnstap
```

Listen for dnstap messages on port 6000.

```
$ dnstap -l 127.0.0.1:6000
```

## USING DNSTAP IN YOUR PLUGIN
In your setup function, check to see if the dnstap plugin is loaded:

```
c.OnStartup(func() error {

    if taph := dnsserver.GetConfig(c).Handler("dnstap"); taph != nil {

        if tapPlugin, ok := taph.(dnstap.Dnstap); ok {

            f.tapPlugin = tapPlugin

        }

    }

    return nil
})
```

And then in your plugin:

```
func (x RandomPlugin) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {

    if tapPlugin != nil {

        q := new(msg.Msg)

        msg.SetQueryTime(q, time.Now())

        msg.SetQueryAddress(q, w.RemoteAddr())

        if tapPlugin.IncludeRawMessage {

            buf, _ := r.Pack() // r has been seen packed/unpacked before, this should not fail

            q.QueryMessage = buf

        }

        msg.SetType(q, tap.Message_CLIENT_QUERY)

        tapPlugin.TapMessage(q)

    }

    // ...
}
```

## SEE ALSO
The website dnstap.info ⟨https://dnstap.info⟩ has info on the dnstap protocol. The forward plugin's dnstap.go uses dnstap to tap messages sent to an upstream.


coredns-erratic

title: coredns-erratic(7)

text:
# coredns-erratic(7)

## NAME
erratic - a plugin useful for testing client behavior.

## DESCRIPTION
erratic returns a static response to all queries, but the responses can be delayed, dropped or truncated. The erratic plugin will respond to every A or AAAA query. For any other type it will return a SERVFAIL response (except AXFR). The reply for A will return 192.0.2.53 (RFC 5737 ⟨https://tools.ietf.org/html/rfc5737⟩), for AAAA it returns 2001:DB8::53 (RFC 3849 ⟨https://tools.ietf.org/html/rfc3849⟩). For an AXFR request it will respond with a small zone transfer.

## SYNTAX

```
erratic {

    drop [AMOUNT]

    truncate [AMOUNT]

    delay [AMOUNT [DURATION]]
}
```

- drop: drop 1 per AMOUNT of queries, the default is 2.

- truncate: truncate 1 per AMOUNT of queries, the default is 2.

- delay: delay 1 per AMOUNT of queries for DURATION, the default for AMOUNT is 2 and the default for DURATION is 100ms.

In case of a zone transfer and truncate the final SOA record isn't added to the response.

## READY
This plugin reports readiness to the ready plugin.

## EXAMPLES

```
example.org {

    erratic {

        drop 3

    }
}
```

Or even shorter if the defaults suit you. Note this only drops queries, it does not delay them.

```
example.org {

    erratic
}
```

Delay 1 in 3 queries for 50ms

```
example.org {

    erratic {

        delay 3 50ms

    }
}
```

Delay 1 in 3 and truncate 1 in 5.

```
example.org {

    erratic {

        delay 3 5ms

        truncate 5

    }
}
```

Drop every second query.

```
example.org {

    erratic {

        drop 2

        truncate 2

    }
}
```

## SEE ALSO
RFC 3849 ⟨https://tools.ietf.org/html/rfc3849⟩ and RFC 5737 ⟨https://tools.ietf.org/html/rfc5737⟩.


coredns-errors

title: coredns-errors(7)

text:
# coredns-errors(7)

## NAME
errors - enables error logging.

## DESCRIPTION
Any errors encountered during the query processing will be printed to standard output. The errors of particular type can be consolidated and printed once per some period of time.

This plugin can only be used once per Server Block.

## SYNTAX
The basic syntax is:

```
errors
```

Extra knobs are available with an expanded syntax:

```
errors {

    consolidate DURATION REGEXP
}
```

Option consolidate allows collecting several error messages matching the regular expression REGEXP during DURATION. After the DURATION since receiving the first such message, the consolidated message will be printed to standard output, e.g.

```
2 errors like '^read udp .* i/o timeout$' occurred in last 30s
```

Multiple consolidate options with different DURATION and REGEXP are allowed. In case if some error message corresponds to several defined regular expressions the message will be associated with the first appropriate REGEXP.

For better performance, it's recommended to use the ^ or $ metacharacters in regular expression when filtering error messages by prefix or suffix, e.g. ^failed to .*, or .* timeout$.

## EXAMPLES
Use the whoami to respond to queries in the example.org domain and Log errors to standard output.

```
example.org {

    whoami

    errors
}
```

Use the forward to resolve queries via 8.8.8.8 and print consolidated error messages for errors with suffix " i/o timeout" or with prefix "Failed to ".

```
. {

    forward . 8.8.8.8

    errors {

        consolidate 5m ".* i/o timeout$"

        consolidate 30s "^Failed to .+"

    }
}
```


coredns-etcd

title: coredns-etcd(7)

text:
# coredns-etcd(7)

## NAME
etcd - enables SkyDNS service discovery from etcd.

## DESCRIPTION
The etcd plugin implements the (older) SkyDNS service discovery service. It is not suitable as a generic DNS zone data plugin. Only a subset of DNS record types are implemented, and subdomains and delegations are not handled at all. The plugin will also recursively descend the tree and return all records found, see "Special Behavior" below for details.

The data in the etcd instance has to be encoded as a message ⟨https://github.com/skynetservices/skydns/blob/2fcff74cdc9f9a7dd64189a447ef27ac354b725f/msg/service.go#L26⟩ like SkyDNS ⟨https://github.com/skynetservices/skydns⟩. It works just like SkyDNS.

The etcd plugin makes extensive use of the forward plugin to forward and query other servers in the network - if that plugin has been enabled as well.

## SYNTAX

```
etcd [ZONES...]
```

•

ZONES zones etcd should be authoritative for.

The path will default to /skydns the local etcd3 proxy (http://localhost:2379 ⟨http://localhost:2379⟩). If no zones are specified the block's zone will be used as the zone.

```
etcd [ZONES...] {

    fallthrough [ZONES...]

    path PATH

    endpoint ENDPOINT...

    credentials USERNAME PASSWORD

    tls CERT KEY CACERT
}
```

- fallthrough If zone matches but 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.

- PATH the path inside etcd. Defaults to "/skydns".

- ENDPOINT the etcd endpoints. Defaults to "http://localhost:2379" ⟨http://localhost:2379"⟩.

- credentials is used to set the USERNAME and PASSWORD for accessing the etcd cluster.

- tls followed by:

–

no arguments, if the server certificate is signed by a system-installed CA and no client cert is needed

–

a single argument that is the CA PEM file, if the server cert is not signed by a system CA and no client cert is needed

–

two arguments - path to cert PEM file, the path to private key PEM file - if the server certificate is signed by a system-installed CA and a client certificate is needed

–

three arguments - path to cert PEM file, path to client private key PEM file, path to CA PEM file - if the server certificate is not signed by a system-installed CA and client certificate is needed.

## SPECIAL BEHAVIOUR
The etcd plugin leverages directory structure to look for related entries. For example an entry /skydns/test/skydns/mx would have entries like /skydns/test/skydns/mx/a, /skydns/test/skydns/mx/b and so on. Similarly a directory /skydns/test/skydns/mx1 will have all mx1 entries. Note this plugin will search through the entire (sub)tree for records. In case of the first example, a query for mx.skydns.text will return both the contents of the a and b records. If the directory extends deeper those records are returned as well.

With etcd3, support for hierarchical keys are dropped ⟨https://coreos.com/etcd/docs/latest/learning/api.html⟩. This means there are no directories but only flat keys with prefixes in etcd3. To accommodate lookups, the etcd plugin now does a lookup on prefix /skydns/test/skydns/mx/ to search for entries like /skydns/test/skydns/mx/a etc, and if there is nothing found on /skydns/test/skydns/mx/, it looks for /skydns/test/skydns/mx to find entries like /skydns/test/skydns/mx1.

This causes two lookups from CoreDNS to etcd in certain cases.

## EXAMPLES
This is the default SkyDNS setup, with everything specified in full:

```
skydns.local {

    etcd {

        path /skydns

        endpoint http://localhost:2379

    }

    prometheus

    cache

    loadbalance
}
. {

    forward . 8.8.8.8:53 8.8.4.4:53

    cache
}
```

Or a setup where we use /etc/resolv.conf as the basis for the proxy and the upstream when resolving external pointing CNAMEs.

```
skydns.local {

    etcd {

        path /skydns

    }

    cache
}
. {

    forward . /etc/resolv.conf

    cache
}
```

Multiple endpoints are supported as well.

```
etcd skydns.local {

    endpoint http://localhost:2379 http://localhost:4001
...
```

Before getting started with these examples, please setup etcdctl (with etcdv3 API) as explained here ⟨https://coreos.com/etcd/docs/latest/dev-guide/interacting_v3.html⟩. This will help you to put sample keys in your etcd server.

If you prefer, you can use curl to populate the etcd server, but with curl the endpoint URL depends on the version of etcd. For instance, etcd v3.2 or before uses only [CLIENT-URL]/v3alpha/* while etcd v3.5 or later uses [CLIENT-URL]/v3/* . Also, Key and Value must be base64 encoded in the JSON payload. With etcdctl these details are automatically taken care of. You can check this document ⟨https://github.com/coreos/etcd/blob/master/Documentation/dev-guide/api_grpc_gateway.md#notes⟩ for details.

### REVERSE ZONES
Reverse zones are supported. You need to make CoreDNS aware of the fact that you are also authoritative for the reverse. For instance if you want to add the reverse for 10.0.0.0/24, you'll need to add the zone 0.0.10.in-addr.arpa to the list of zones. Showing a snippet of a Corefile:

```
etcd skydns.local 10.0.0.0/24 {
...
```

Next you'll need to populate the zone with reverse records, here we add a reverse for 10.0.0.127 pointing to reverse.skydns.local.

```
% etcdctl put /skydns/arpa/in-addr/10/0/0/127 '{"host":"reverse.skydns.local."}'
```

Querying with dig:

```
% dig @localhost -x 10.0.0.127 +short
reverse.skydns.local.
```

### ZONE NAME AS A RECORD
The zone name itself can be used as an A record. This behavior can be achieved by writing special entries to the ETCD path of your zone. If your zone is named skydns.local for example, you can create an A record for this zone as follows:

```
% etcdctl put /skydns/local/skydns/ '{"host":"1.1.1.1","ttl":60}'
```

If you query the zone name itself, you will receive the created A record:

```
% dig +short skydns.local @localhost
1.1.1.1
```

If you would like to use DNS RR for the zone name, you can set the following:

```
% etcdctl put /skydns/local/skydns/x1 '{"host":"1.1.1.1","ttl":60}'
% etcdctl put /skydns/local/skydns/x2 '{"host":"1.1.1.2","ttl":60}'
```

If you query the zone name now, you will get the following response:

```
% dig +short skydns.local @localhost
1.1.1.1
1.1.1.2
```

### ZONE NAME AS AAAA RECORD
If you would like to use AAAA records for the zone name too, you can set the following:

```
% etcdctl put /skydns/local/skydns/x3 '{"host":"2003::8:1","ttl":60}'
% etcdctl put /skydns/local/skydns/x4 '{"host":"2003::8:2","ttl":60}'
```

If you query the zone name for AAAA now, you will get the following response:

```
% dig +short skydns.local AAAA @localhost
2003::8:1
2003::8:2
```

### SRV RECORD
If you would like to use SRV records, you can set the following:

```
% etcdctl put /skydns/local/skydns/x5 '{"host":"skydns-local.server","ttl":60,"priority":10,"port":8080}'
```

Please notice that the key host is the target in SRV, so it should be a domain name.

If you query the zone name for SRV now, you will get the following response:

```
% dig +short skydns.local SRV @localhost
10 100 8080 skydns-local.server.
```

### TXT RECORD
If you would like to use TXT records, you can set the following:

```
% etcdctl put /skydns/local/skydns/x6 '{"ttl":60,"text":"this is a random text message."}'
```

If you query the zone name for TXT now, you will get the following response:

```
% dig +short skydns.local TXT @localhost
"this is a random text message."
```

## SEE ALSO
If you want to round robin A and AAAA responses look at the loadbalance plugin.


coredns-file

title: coredns-file(7)

text:
# coredns-file(7)

## NAME
file - enables serving zone data from an RFC 1035-style master file.

## DESCRIPTION
The file plugin is used for an "old-style" DNS server. It serves from a preloaded file that exists on disk contained RFC 1035 styled data. If the zone file contains signatures (i.e., is signed using DNSSEC), correct DNSSEC answers are returned. Only NSEC is supported! If you use this setup you are responsible for re-signing the zonefile.

## SYNTAX

```
file DBFILE [ZONES...]
```

- DBFILE the 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 authoritative for. If empty, the zones from the configuration block are used.

If you want to round-robin A and AAAA responses look at the loadbalance plugin.

```
file DBFILE [ZONES... ] {

    reload DURATION
}
```

•

reload interval to perform a reload of the zone if the SOA version changes. Default is one minute. Value of 0 means to not scan for changes and reload. For example, 30s checks the zonefile every 30 seconds and reloads the zone when serial changes.

If you need outgoing zone transfers, take a look at the transfer plugin.

## EXAMPLES
Load the example.org zone from db.example.org and allow transfers to the internet, but send notifies to 10.240.1.1

```
example.org {

    file db.example.org

    transfer {

        to * 10.240.1.1

    }
}
```

Where db.example.org would contain RRSets (https://tools.ietf.org/html/rfc7719#section-4 ⟨https://tools.ietf.org/html/rfc7719#section-4⟩) in the (text) presentation format from RFC 1035:

```
$ORIGIN example.org.
@    3600 IN    SOA sns.dns.icann.org. noc.dns.icann.org. 2017042745 7200 3600 1209600 3600

    3600 IN NS a.iana-servers.net.

    3600 IN NS b.iana-servers.net.
www     IN A     127.0.0.1

        IN AAAA  ::1
```

Or use a single zone file for multiple zones:

```
. {

    file example.org.signed example.org example.net

    transfer example.org example.net {

        to * 10.240.1.1

    }
}
```

Note that if you have a configuration like the following you may run into a problem of the origin not being correctly recognized:

```
. {

    file db.example.org
}
```

We omit the origin for the file db.example.org, so this references the zone in the server block, which, in this case, is the root zone. Any contents of db.example.org will then read with that origin set; this may or may not do what you want. It's better to be explicit here and specify the correct origin. This can be done in two ways:

```
. {

    file db.example.org example.org
}
```

Or

```
example.org {

    file db.example.org
}
```

## SEE ALSO
See the loadbalance plugin if you need simple record shuffling. And the transfer plugin for zone transfers. Lastly the root plugin can help you specify the location of the zone files.

See RFC 1035 ⟨https://www.rfc-editor.org/rfc/rfc1035.txt⟩ for more info on how to structure zone files.


coredns-forward

title: coredns-forward(7)

text:
# coredns-forward(7)

## NAME
forward - facilitates proxying DNS messages to upstream resolvers.

## DESCRIPTION
The forward plugin re-uses already opened sockets to the upstreams. It supports UDP, TCP and DNS-over-TLS and uses in band health checking.

When it detects an error a health check is performed. This checks runs in a loop, performing each check at a 0.5s interval for as long as the upstream reports unhealthy. Once healthy we stop health checking (until the next error). The health checks use a recursive DNS query (. IN NS) to get upstream health. Any response that is not a network error (REFUSED, NOTIMPL, SERVFAIL, etc) is taken as a healthy upstream. The health check uses the same protocol as specified in TO. If max_fails is set to 0, no checking is performed and upstreams will always be considered healthy.

When all upstreams are down it assumes health checking as a mechanism has failed and will try to connect to a random upstream (which may or may not work).

This plugin can only be used once per Server Block.

## SYNTAX
In its most basic form, a simple forwarder uses this syntax:

```
forward FROM TO...
```

- FROM is the base domain to match for the request to be forwarded.

- TO... are the destination endpoints to forward to. The TO syntax allows you to specify a protocol, tls://9.9.9.9 or dns:// (or no protocol) for plain DNS. The number of upstreams is limited to 15.

Multiple upstreams are randomized (see policy) on first use. When a healthy proxy returns an error during the exchange the next upstream in the list is tried.

Extra knobs are available with an expanded syntax:

```
forward FROM TO... {

    except IGNORED_NAMES...

    force_tcp

    prefer_udp

    expire DURATION

    max_fails INTEGER

    tls CERT KEY CA

    tls_servername NAME

    policy random|round_robin|sequential

    health_check DURATION [no_rec]

    max_concurrent MAX
}
```

- FROM and TO... as above.

- IGNORED_NAMES in except is a space-separated list of domains to exclude from forwarding. Requests that match none of these names will be passed through.

- force_tcp, use TCP even when the request comes in over UDP.

- prefer_udp, try first using UDP even when the request comes in over TCP. If response is truncated (TC flag set in response) then do another attempt over TCP. In case if both force_tcp and prefer_udp options specified the force_tcp takes precedence.

- max_fails is the number of subsequent failed health checks that are needed before considering an upstream to be down. If 0, the upstream will never be marked as down (nor health checked). Default is 2.

- expire DURATION, expire (cached) connections after this time, the default is 10s.

- tls CERT KEY CA define the TLS properties for TLS connection. From 0 to 3 arguments can be provided with the meaning as described below

–

tls - no client authentication is used, and the system CAs are used to verify the server certificate

–

tls CA - no client authentication is used, and the file CA is used to verify the server certificate

–

tls CERT KEY - client authentication is used with the specified cert/key pair. The server certificate is verified with the system CAs

–

tls CERT KEY CA - client authentication is used with the specified cert/key pair. The server certificate is verified using the specified CA file

- tls_servername NAME allows you to set a server name in the TLS configuration; for instance 9.9.9.9 needs this to be set to dns.quad9.net. Multiple upstreams are still allowed in this scenario, but they have to use the same tls_servername. E.g. mixing 9.9.9.9 (QuadDNS) with 1.1.1.1 (Cloudflare) will not work.

- policy specifies the policy to use for selecting upstream servers. The default is random.

–

random is a policy that implements random upstream selection.

–

round_robin is a policy that selects hosts based on round robin ordering.

–

sequential is a policy that selects hosts based on sequential ordering.

•

health_check configure the behaviour of health checking of the upstream servers

–

<duration> - use a different duration for health checking, the default duration is 0.5s.

–

no_rec - optional argument that sets the RecursionDesired-flag of the dns-query used in health checking to false. The flag is default true.

•

max_concurrent MAX will limit the number of concurrent queries to MAX. Any new query that would raise the number of concurrent queries above the MAX will result in a REFUSED response. This response does not count as a health failure. When choosing a value for MAX, pick a number at least greater than the expected upstream query rate * latency of the upstream servers. As an upper bound for MAX, consider that each concurrent query will use about 2kb of memory.

Also note the TLS config is "global" for the whole forwarding proxy if you need a different tls-name for different upstreams you're out of luck.

On each endpoint, the timeouts for communication are set as follows:

- The dial timeout by default is 30s, and can decrease automatically down to 100ms based on early results.

- The read timeout is static at 2s.

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

•

forward/upstream: the upstream used to forward the request

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

- coredns_forward_requests_total{to} - query count per upstream.

- coredns_forward_responses_total{to} - Counter of responses received per upstream.

- coredns_forward_request_duration_seconds{to, rcode, type} - duration per upstream, RCODE, type

- coredns_forward_responses_total{to, rcode} - count of RCODEs per upstream.

- coredns_forward_healthcheck_failures_total{to} - number of failed health checks per upstream.

- coredns_forward_healthcheck_broken_total{} - counter of when all upstreams are unhealthy, and we are randomly (this always uses the random policy) spraying to an upstream.

- coredns_forward_max_concurrent_rejects_total{} - counter of the number of queries rejected because the number of concurrent queries were at maximum.

- coredns_forward_conn_cache_hits_total{to, proto} - counter of connection cache hits per upstream and protocol.

- coredns_forward_conn_cache_misses_total{to, proto} - counter of connection cache misses per upstream and protocol. Where to is one of the upstream servers (TO from the config), rcode is the returned RCODE from the upstream, proto is the transport protocol like udp, tcp, tcp-tls.

## EXAMPLES
Proxy all requests within example.org. to a nameserver running on a different port:

```
example.org {

    forward . 127.0.0.1:9005
}
```

Load balance all requests between three resolvers, one of which has a IPv6 address.

```
. {

    forward . 10.0.0.10:53 10.0.0.11:1053 [2003::1]:53
}
```

Forward everything except requests to example.org

```
. {

    forward . 10.0.0.10:1234 {

        except example.org

    }
}
```

Proxy everything except example.org using the host's resolv.conf's nameservers:

```
. {

    forward . /etc/resolv.conf {

        except example.org

    }
}
```

Proxy all requests to 9.9.9.9 using the DNS-over-TLS (DoT) protocol, and cache every answer for up to 30 seconds. Note the tls_servername is mandatory if you want a working setup, as 9.9.9.9 can't be used in the TLS negotiation. Also set the health check duration to 5s to not completely swamp the service with health checks.

```
. {

    forward . tls://9.9.9.9 {

       tls_servername dns.quad9.net

       health_check 5s

    }

    cache 30
}
```

Or with multiple upstreams from the same provider

```
. {

    forward . tls://1.1.1.1 tls://1.0.0.1 {

       tls_servername cloudflare-dns.com

       health_check 5s

    }

    cache 30
}
```

Or when you have multiple DoT upstreams with different tls_servernames, you can do the following:

```
. {

    forward . 127.0.0.1:5301 127.0.0.1:5302
}
.:5301 {

    forward . 8.8.8.8 8.8.4.4 {

        tls_servername dns.google

    }
}
.:5302 {

    forward . 1.1.1.1 1.0.0.1 {

        tls_servername cloudflare-dns.com

    }
}
```

## SEE ALSO
RFC 7858 ⟨https://tools.ietf.org/html/rfc7858⟩ for DNS over TLS.


coredns-geoip

title: coredns-geoip(7)

text:
# coredns-geoip(7)

## NAME
geoip - Lookup maxmind geoip2 databases using the client IP, then add associated geoip data to the context request.

## DESCRIPTION
The geoip plugin add geo location data associated with the client IP, it allows you to configure a geoIP2 maxmind database ⟨https://dev.maxmind.com/geoip/docs/databases⟩ to add the geo location data associated with the IP address.

The data is added leveraging the metadata plugin, values can then be retrieved using it as well, for example:

```
import (

    "strconv"

    "github.com/coredns/coredns/plugin/metadata"
)
// ...
if getLongitude := metadata.ValueFunc(ctx, "geoip/longitude"); getLongitude != nil {

    if longitude, err := strconv.ParseFloat(getLongitude(), 64); err == nil {

        // Do something useful with longitude.

    }
} else {

    // The metadata label geoip/longitude for some reason, was not set.
}
// ...
```

## DATABASES
The supported databases use city schema such as City and Enterprise. Other databases types with different schemas are not supported yet.

You can download a free and public City database ⟨https://dev.maxmind.com/geoip/geolite2-free-geolocation-data⟩.

## SYNTAX

```
geoip [DBFILE]
```

•

DBFILE the mmdb database file path.

## EXAMPLES
The following configuration configures the City database.

```
. {

    geoip /opt/geoip2/db/GeoLite2-City.mmdb

    metadata # Note that metadata plugin must be enabled as well.
}
```

## METADATADA LABELS
A limited set of fields will be exported as labels, all values are stored using strings regardless of their underlying value type, and therefore you may have to convert it back to its original type, note that numeric values are always represented in base 10.

Label

Type

Example

Description

geoip/city/name

string

Cambridge

Then city name in English language.

geoip/country/code

string

GB

Country ISO 3166-1

⟨https://en.wikipedia.org/wiki/ISO_3166-1⟩ code.

geoip/country/name

string

United Kingdom

The country name in English language.

geoip/country/is_in_european_union

bool

false

Either true or false.

geoip/continent/code

string

EU

See Continent codes

⟨#ContinentCodes⟩.

geoip/continent/name

string

Europe

The continent name in English language.

geoip/latitude

float64

52.2242

Base 10, max available precision.

geoip/longitude

float64

0.1315

Base 10, max available precision.

geoip/timezone

string

Europe/London

The timezone.

geoip/postalcode

string

CB4

The postal code.

## CONTINENT CODES
Value

Continent (EN)

AF

Africa

AN

Antarctica

AS

Asia

EU

Europe

NA

North America

OC

Oceania

SA

South America


coredns-grpc

title: coredns-grpc(7)

text:
# coredns-grpc(7)

## NAME
grpc - facilitates proxying DNS messages to upstream resolvers via gRPC protocol.

## DESCRIPTION
The grpc plugin supports gRPC and TLS.

This plugin can only be used once per Server Block.

## SYNTAX
In its most basic form:

```
grpc FROM TO...
```

- FROM is the base domain to match for the request to be proxied.

- TO... are the destination endpoints to proxy to. The number of upstreams is limited to 15.

Multiple upstreams are randomized (see policy) on first use. When a proxy returns an error the next upstream in the list is tried.

Extra knobs are available with an expanded syntax:

```
grpc FROM TO... {

    except IGNORED_NAMES...

    tls CERT KEY CA

    tls_servername NAME

    policy random|round_robin|sequential
}
```

- FROM and TO... as above.

- IGNORED_NAMES in except is a space-separated list of domains to exclude from proxying. Requests that match none of these names will be passed through.

- tls CERT KEY CA define the TLS properties for TLS connection. From 0 to 3 arguments can be provided with the meaning as described below

–

tls - no client authentication is used, and the system CAs are used to verify the server certificate

–

tls CA - no client authentication is used, and the file CA is used to verify the server certificate

–

tls CERT KEY - client authentication is used with the specified cert/key pair. The server certificate is verified with the system CAs

–

tls CERT KEY CA - client authentication is used with the specified cert/key pair. The server certificate is verified using the specified CA file

- tls_servername NAME allows you to set a server name in the TLS configuration; for instance 9.9.9.9 needs this to be set to dns.quad9.net. Multiple upstreams are still allowed in this scenario, but they have to use the same tls_servername. E.g. mixing 9.9.9.9 (QuadDNS) with 1.1.1.1 (Cloudflare) will not work.

- policy specifies the policy to use for selecting upstream servers. The default is random.

Also note the TLS config is "global" for the whole grpc proxy if you need a different tls-name for different upstreams you're out of luck.

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

- coredns_grpc_request_duration_seconds{to} - duration per upstream interaction.

- coredns_grpc_requests_total{to} - query count per upstream.

- coredns_grpc_responses_total{to, rcode} - count of RCODEs per upstream. and we are randomly (this always uses the random policy) spraying to an upstream.

## EXAMPLES
Proxy all requests within example.org. to a nameserver running on a different port:

```
example.org {

    grpc . 127.0.0.1:9005
}
```

Load balance all requests between three resolvers, one of which has a IPv6 address.

```
. {

    grpc . 10.0.0.10:53 10.0.0.11:1053 [2003::1]:53
}
```

Forward everything except requests to example.org

```
. {

    grpc . 10.0.0.10:1234 {

        except example.org

    }
}
```

Proxy everything except example.org using the host's resolv.conf's nameservers:

```
. {

    grpc . /etc/resolv.conf {

        except example.org

    }
}
```

Proxy all requests to 9.9.9.9 using the TLS protocol, and cache every answer for up to 30 seconds. Note the tls_servername is mandatory if you want a working setup, as 9.9.9.9 can't be used in the TLS negotiation.

```
. {

    grpc . 9.9.9.9 {

       tls_servername dns.quad9.net

    }

    cache 30
}
```

Or with multiple upstreams from the same provider

```
. {

    grpc . 1.1.1.1 1.0.0.1 {

       tls_servername cloudflare-dns.com

    }

    cache 30
}
```

## BUGS
The TLS config is global for the whole grpc proxy if you need a different tls_servername for different upstreams you're out of luck.


coredns-header

title: coredns-header(7)

text:
# coredns-header(7)

## NAME
header - modifies the header for responses.

## DESCRIPTION
header ensures that the flags are in the desired state for responses. The modifications are made transparently for the client.

## SYNTAX

```
header {

    ACTION FLAGS...

    ACTION FLAGS...
}
```

•

ACTION defines the state for DNS message header flags. Actions are evaluated in the order they are defined so last one has the most precedence. Allowed values are:

–

set

–

clear

•

FLAGS are the DNS header flags that will be modified. Current supported flags include:

–

aa - Authoritative(Answer)

–

ra - RecursionAvailable

–

rd - RecursionDesired

## EXAMPLES
Make sure recursive available ra flag is set in all the responses:

```
. {

    header {

        set ra

    }
}
```

Make sure "recursion available" ra and "authoritative answer" aa flags are set and "recursion desired" is cleared in all responses:

```
. {

    header {

        set ra aa

        clear rd

    }
}
```


coredns-health

title: coredns-health(7)

text:
# coredns-health(7)

## NAME
health - enables a health check endpoint.

## DESCRIPTION
Enabled process wide health endpoint. When CoreDNS is up and running this returns a 200 OK HTTP status code. The health is exported, by default, on port 8080/health.

## SYNTAX

```
health [ADDRESS]
```

Optionally takes an address; the default is :8080. The health path is fixed to /health. The health endpoint returns a 200 response code and the word "OK" when this server is healthy.

An extra option can be set with this extended syntax:

```
health [ADDRESS] {

    lameduck DURATION
}
```

•

Where lameduck will delay shutdown for DURATION. /health will still answer 200 OK. Note: The ready plugin will not answer OK while CoreDNS is in lameduck mode prior to shutdown.

If you have multiple Server Blocks, health can only be enabled in one of them (as it is process wide). If you really need multiple endpoints, you must run health endpoints on different ports:

```
com {

    whoami

    health :8080
}
net {

    erratic

    health :8081
}
```

Doing this is supported but both endpoints ":8080" and ":8081" will export the exact same health.

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

•

coredns_health_request_duration_seconds{} - duration to process a HTTP query to the local /health endpoint. As this a local operation it should be fast. A (large) increase in this duration indicates the CoreDNS process is having trouble keeping up with its query load.

Note that this metric does not have a server label, because being overloaded is a symptom of the running process, not a specific server.

## EXAMPLES
Run another health endpoint on http://localhost:8091 ⟨http://localhost:8091⟩.

```
. {

    health localhost:8091
}
```

Set a lameduck duration of 1 second:

```
. {

    health localhost:8092 {

        lameduck 1s

    }
}
```


coredns-hosts

title: coredns-hosts(7)

text:
# coredns-hosts(7)

## NAME
hosts - enables serving zone data from a /etc/hosts style file.

## DESCRIPTION
The hosts plugin is useful for serving zones from a /etc/hosts file. It serves from a preloaded file that exists on disk. It checks the file for changes and updates the zones accordingly. This plugin only supports A, AAAA, and PTR records. The hosts plugin can be used with readily available hosts files that block access to advertising servers.

The plugin reloads the content of the hosts file every 5 seconds. Upon reload, CoreDNS will use the new definitions. Should the file be deleted, any inlined content will continue to be served. When the file is restored, it will then again be used.

If you want to pass the request to the rest of the plugin chain if there is no match in the hosts plugin, you must specify the fallthrough option.

This plugin can only be used once per Server Block.

## THE HOSTS FILE
Commonly the entries are of the form IP_address canonical_hostname [aliases...] as explained by the hosts(5) man page.

Examples:

```
127.0.0.1       localhost
192.168.1.10    example.com            example
::1                     localhost ip6-localhost ip6-loopback
fdfc:a744:27b5:3b0e::1  example.com example
```

### PTR RECORDS
PTR records for reverse lookups are generated automatically by CoreDNS (based on the hosts file entries) and cannot be created manually.

## SYNTAX

```
hosts [FILE [ZONES...]] {

    [INLINE]

    ttl SECONDS

    no_reverse

    reload DURATION

    fallthrough [ZONES...]
}
```

- FILE the hosts file to read and parse. If the path is relative the path from the root plugin will be prepended to it. Defaults to /etc/hosts if omitted. We scan the file for changes every 5 seconds.

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

- INLINE the hosts file contents inlined in Corefile. If there are any lines before fallthrough then all of them will be treated as the additional content for hosts file. The specified hosts file path will still be read but entries will be overridden.

- ttl change the DNS TTL of the records generated (forward and reverse). The default is 3600 seconds (1 hour).

- reload change the period between each hostsfile reload. A time of zero seconds disables the feature. Examples of valid durations: "300ms", "1.5h" or "2h45m". See Go's time ⟨https://godoc.org/time⟩. package.

- no_reverse disable the automatic generation of the in-addr.arpa or ip6.arpa entries for the hosts

- 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.

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

- coredns_hosts_entries{} - The combined number of entries in hosts and Corefile.

- coredns_hosts_reload_timestamp_seconds{} - The timestamp of the last reload of hosts file.

## EXAMPLES
Load /etc/hosts file.

```
. {

    hosts
}
```

Load example.hosts file in the current directory.

```
. {

    hosts example.hosts
}
```

Load example.hosts file and only serve example.org and example.net from it and fall through to the next plugin if query doesn't match.

```
. {

    hosts example.hosts example.org example.net {

        fallthrough

    }
}
```

Load hosts file inlined in Corefile.

```
example.hosts example.org {

    hosts {

        10.0.0.1 example.org

        fallthrough

    }

    whoami
}
```

## SEE ALSO
The form of the entries in the /etc/hosts file are based on IETF RFC 952 ⟨https://tools.ietf.org/html/rfc952⟩ which was updated by IETF RFC 1123 ⟨https://tools.ietf.org/html/rfc1123⟩.


coredns-import

title: coredns-import(7)

text:
# coredns-import(7)

## NAME
import - includes files or references snippets from a Corefile.

## DESCRIPTION
The import plugin can be used to include files into the main configuration. Another use is to reference predefined snippets. Both can help to avoid some duplication.

This is a unique plugin in that import can appear outside of a server block. In other words, it can appear at the top of a Corefile where an address would normally be.

## SYNTAX

```
import PATTERN
```

•

PATTERN is the file, glob pattern (*) or snippet to include. Its contents will replace this line, as if that file's contents appeared here to begin with.

## FILES
You can use import to include a file or files. This file's location is relative to the Corefile's location. It is an error if a specific file cannot be found, but an empty glob pattern is not an error.

## SNIPPETS
You can define snippets to be reused later in your Corefile by defining a block with a single-token label surrounded by parentheses:

```
(mysnippet) {

    ...
}
```

Then you can invoke the snippet with import:

```
import mysnippet
```

## EXAMPLES
Import a shared configuration:

```
. {

   import config/common.conf
}
```

Where config/common.conf contains:

```
prometheus
errors
log
```

This imports files found in the zones directory:

```
import ../zones/*
```

## SEE ALSO
See corefile(5).


title: coredns-k8s_external(7)

text:
# coredns-k8s_external(7)

## NAME
k8s_external - resolves load balancer and external IPs from outside Kubernetes clusters.

## DESCRIPTION
This plugin allows an additional zone to resolve the external IP address(es) of a Kubernetes service. This plugin is only useful if the kubernetes plugin is also loaded.

The plugin uses an external zone to resolve in-cluster IP addresses. It only handles queries for A, AAAA and SRV records; all others result in NODATA responses. To make it a proper DNS zone, it handles SOA and NS queries for the apex of the zone.

By default the apex of the zone will look like the following (assuming the zone used is example.org):

```
example.org.    5 IN    SOA ns1.dns.example.org. hostmaster.example.org. (

                12345      ; serial

                14400      ; refresh (4 hours)

                3600       ; retry (1 hour)

                604800     ; expire (1 week)

                5          ; minimum (4 hours)

                )
example.org        5 IN    NS ns1.dns.example.org.
ns1.dns.example.org.  5 IN  A    ....
ns1.dns.example.org.  5 IN  AAAA ....
```

Note that we use the dns subdomain for the records DNS needs (see the apex directive). Also note the SOA's serial number is static. The IP addresses of the nameserver records are those of the CoreDNS service.

The k8s_external plugin handles the subdomain dns and the apex of the zone itself; all other queries are resolved to addresses in the cluster.

## SYNTAX

```
k8s_external [ZONE...]
```

•

ZONES zones k8s_external should be authoritative for.

If you want to change the apex domain or use a different TTL for the returned records you can use this extended syntax.

```
k8s_external [ZONE...] {

    apex APEX

    ttl TTL
}
```

- APEX is the name (DNS label) to use for the apex records; it defaults to dns.

- ttl allows you to set a custom TTL for responses. The default is 5 (seconds).

## EXAMPLES
Enable names under example.org to be resolved to in-cluster DNS addresses.

```
. {

   kubernetes cluster.local

   k8s_external example.org
}
```

With the Corefile above, the following Service will get an A record for test.default.example.org with the IP address 192.168.200.123.

```
apiVersion: v1
kind: Service
metadata:

 name: test

 namespace: default
spec:

 clusterIP: None

 externalIPs:

 - 192.168.200.123

 type: ClusterIP
```

For some background see resolve external IP address ⟨https://github.com/kubernetes/dns/issues/242⟩. And A records for services with Load Balancer IP ⟨https://github.com/coredns/coredns/issues/1851⟩.

PTR queries for the reverse zone is not supported.


coredns-kubernetes

title: coredns-kubernetes(7)

text:
# coredns-kubernetes(7)

## NAME
kubernetes - enables reading zone data from a Kubernetes cluster.

## DESCRIPTION
This plugin implements the Kubernetes DNS-Based Service Discovery Specification ⟨https://github.com/kubernetes/dns/blob/master/docs/specification.md⟩.

CoreDNS running the kubernetes plugin can be used as a replacement for kube-dns in a kubernetes cluster. See the deployment ⟨https://github.com/coredns/deployment⟩ repository for details on how to deploy CoreDNS in Kubernetes ⟨https://github.com/coredns/deployment/tree/master/kubernetes⟩.

stubDomains and upstreamNameservers ⟨https://kubernetes.io/blog/2017/04/configuring-private-dns-zones-upstream-nameservers-kubernetes/⟩ are implemented via the forward plugin. See the examples below.

This plugin can only be used once per Server Block.

## SYNTAX

```
kubernetes [ZONES...]
```

With only the plugin specified, the kubernetes plugin will default to the zone specified in the server's block. It will handle all queries in that zone and connect to Kubernetes in-cluster. It will not provide PTR records for services or A records for pods. If ZONES is used it specifies all the zones the plugin should be authoritative for.

```
kubernetes [ZONES...] {

    endpoint URL

    tls CERT KEY CACERT

    kubeconfig KUBECONFIG [CONTEXT]

    namespaces NAMESPACE...

    labels EXPRESSION

    pods POD-MODE

    endpoint_pod_names

    ttl TTL

    noendpoints

    fallthrough [ZONES...]

    ignore empty_service
}
```

- endpoint specifies the URL for a remote k8s API endpoint. If omitted, it will connect to k8s in-cluster using the cluster service account.

- tls CERT KEY CACERT are the TLS cert, key and the CA cert file names for remote k8s connection. This option is ignored if connecting in-cluster (i.e. endpoint is not specified).

- kubeconfig KUBECONFIG [CONTEXT] authenticates the connection to a remote k8s cluster using a kubeconfig file. [CONTEXT] is optional, if not set, then the current context specified in kubeconfig will be used. It supports TLS, username and password, or token-based authentication. This option is ignored if connecting in-cluster (i.e., the endpoint is not specified).

- namespaces NAMESPACE [NAMESPACE...] only exposes the k8s namespaces listed. If this option is omitted all namespaces are exposed

- namespace_labels EXPRESSION only expose the records for Kubernetes namespaces that match this label selector. The label selector syntax is described in the Kubernetes User Guide - Labels ⟨https://kubernetes.io/docs/user-guide/labels/⟩. An example that only exposes namespaces labeled as "istio-injection=enabled", would use: labels istio-injection=enabled.

- labels EXPRESSION only exposes the records for Kubernetes objects that match this label selector. The label selector syntax is described in the Kubernetes User Guide - Labels ⟨https://kubernetes.io/docs/user-guide/labels/⟩. An example that only exposes objects labeled as "application=nginx" in the "staging" or "qa" environments, would use: labels environment in (staging, qa),application=nginx.

- pods POD-MODE sets the mode for handling IP-based pod A records, e.g. 1-2-3-4.ns.pod.cluster.local. in A 1.2.3.4. This option is provided to facilitate use of SSL certs when connecting directly to pods. Valid values for POD-MODE:

–

disabled: Default. Do not process pod requests, always returning NXDOMAIN

–

insecure: Always return an A record with IP from request (without checking k8s). This option is vulnerable to abuse if used maliciously in conjunction with wildcard SSL certs. This option is provided for backward compatibility with kube-dns.

–

verified: Return an A record if there exists a pod in same namespace with matching IP. This option requires substantially more memory than in insecure mode, since it will maintain a watch on all pods.

- endpoint_pod_names uses the pod name of the pod targeted by the endpoint as the endpoint name in A records, e.g., endpoint-name.my-service.namespace.svc.cluster.local. in A 1.2.3.4 By default, the endpoint-name name selection is as follows: Use the hostname of the endpoint, or if hostname is not set, use the dashed form of the endpoint IP address (e.g., 1-2-3-4.my-service.namespace.svc.cluster.local.) If this directive is included, then name selection for endpoints changes as follows: Use the hostname of the endpoint, or if hostname is not set, use the pod name of the pod targeted by the endpoint. If there is no pod targeted by the endpoint, use the dashed IP address form.

- ttl allows you to set a custom TTL for responses. The default is 5 seconds. The minimum TTL allowed is 0 seconds, and the maximum is capped at 3600 seconds. Setting TTL to 0 will prevent records from being cached.

- noendpoints will turn off the serving of endpoint records by disabling the watch on endpoints. All endpoint queries and headless service queries will result in an NXDOMAIN.

- fallthrough [ZONES...] If a query for a record in the zones for which the plugin is authoritative results in NXDOMAIN, normally that is what the response will be. However, if you specify this option, the query will instead be passed on down the plugin chain, which can include another plugin to handle the query. 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.

- ignore empty_service returns NXDOMAIN for services without any ready endpoint addresses (e.g., ready pods). This allows the querying pod to continue searching for the service in the search path. The search path could, for example, include another Kubernetes cluster.

Enabling zone transfer is done by using the transfer plugin.

## READY
This plugin reports readiness to the ready plugin. This will happen after it has synced to the Kubernetes API.

## EXAMPLES
Handle all queries in the cluster.local zone. Connect to Kubernetes in-cluster. Also handle all in-addr.arpa PTR requests for 10.0.0.0/17 . Verify the existence of pods when answering pod requests.

```
10.0.0.0/17 cluster.local {

    kubernetes {

        pods verified

    }
}
```

Or you can selectively expose some namespaces:

```
kubernetes cluster.local {

    namespaces test staging
}
```

Connect to Kubernetes with CoreDNS running outside the cluster:

```
kubernetes cluster.local {

    endpoint https://k8s-endpoint:8443

    tls cert key cacert
}
```

## STUBDOMAINS AND UPSTREAMNAMESERVERS
Here we use the forward plugin to implement a stubDomain that forwards example.local to the nameserver 10.100.0.10:53. Also configured is an upstreamNameserver 8.8.8.8:53 that will be used for resolving names that do not fall in cluster.local or example.local.

```
cluster.local:53 {

    kubernetes cluster.local
}
example.local {

    forward . 10.100.0.10:53
}
. {

    forward . 8.8.8.8:53
}
```

The configuration above represents the following Kube-DNS stubDomains and upstreamNameservers configuration.

```
stubDomains: |

   {“example.local”: [“10.100.0.10:53”]}
upstreamNameservers: |

   [“8.8.8.8:53”]
```

## AUTOPATH
The kubernetes plugin can be used in conjunction with the autopath plugin. Using this feature enables server-side domain search path completion in Kubernetes clusters. Note: pods must be set to verified for this to function properly. Furthermore, the remote IP address in the DNS packet received by CoreDNS must be the IP address of the Pod that sent the request.

```
cluster.local {

    autopath @kubernetes

    kubernetes {

        pods verified

    }
}
```

## WILDCARDS
Some query labels accept a wildcard value to match any value. If a label is a valid wildcard (*, or the word "any"), then that label will match all values. The labels that accept wildcards are:

- endpoint in an A record request: endpoint.service.namespace.svc.zone, e.g., *.nginx.ns.svc.cluster.local

- service in an A record request: service.namespace.svc.zone, e.g., *.ns.svc.cluster.local

- namespace in an A record request: service.namespace.svc.zone, e.g., nginx.*.svc.cluster.local

- port and/or protocol in an SRV request: port_.protocol_.service.namespace.svc.zone., e.g., _http.*.service.ns.svc.cluster.local

- multiple wildcards are allowed in a single query, e.g., A Request *.*.svc.zone. or SRV request *.*.*.*.svc.zone.

For example, wildcards can be used to resolve all Endpoints for a Service as A records. e.g.: *.service.ns.svc.myzone.local will return the Endpoint IPs in the Service service in namespace default:

```
*.service.default.svc.cluster.local. 5    IN A    192.168.10.10
*.service.default.svc.cluster.local. 5    IN A    192.168.25.15
```

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

- kubernetes/endpoint: the endpoint name in the query

- kubernetes/kind: the resource kind (pod or svc) in the query

- kubernetes/namespace: the namespace in the query

- kubernetes/port-name: the port name in an SRV query

- kubernetes/protocol: the protocol in an SRV query

- kubernetes/service: the service name in the query

- kubernetes/client-namespace: the client pod's namespace (see requirements below)

- kubernetes/client-pod-name: the client pod's name (see requirements below)

The kubernetes/client-namespace and kubernetes/client-pod-name metadata work by reconciling the client IP address in the DNS request packet to a known pod IP address. Therefore the following is required:

* pods verified mode must be enabled

* the remote IP address in the DNS packet received by CoreDNS must be the IP address

of the Pod that sent the request.

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

•

coredns_kubernetes_dns_programming_duration_seconds{service_kind} - Exports the DNS programming latency SLI ⟨https://github.com/kubernetes/community/blob/master/sig-scalability/slos/dns_programming_latency.md⟩. The metrics has the service_kind label that identifies the kind of the kubernetes service ⟨https://kubernetes.io/docs/concepts/services-networking/service⟩. It may take one of the three values:

–

cluster_ip

–

headless_with_selector

–

headless_without_selector

## BUGS
The duration metric only supports the "headless_with_selector" service currently.

## SEE ALSO
See the autopath plugin to enable search path optimizations. And use the transfer plugin to enable outgoing zone transfers.


coredns-loadbalance

title: coredns-loadbalance(7)

text:
# coredns-loadbalance(7)

## NAME
loadbalance - randomizes the order of A, AAAA and MX records.

## DESCRIPTION
The loadbalance will act as a round-robin DNS load balancer by randomizing the order of A, AAAA, and MX records in the answer.

See Wikipedia ⟨https://en.wikipedia.org/wiki/Round-robin_DNS⟩ about the pros and cons of this setup. It will take care to sort any CNAMEs before any address records, because some stub resolver implementations (like glibc) are particular about that.

## SYNTAX

```
loadbalance [POLICY]
```

•

POLICY is how to balance. The default, and only option, is "round_robin".

## EXAMPLES
Load balance replies coming back from Google Public DNS:

```
. {

    loadbalance round_robin

    forward . 8.8.8.8 8.8.4.4
}
```


coredns-local

title: coredns-local(7)

text:
# coredns-local(7)

## NAME
local - respond to local names.

## DESCRIPTION
local will respond with a basic reply to a "local request". Local request are defined to be names in the following zones: localhost, 0.in-addr.arpa, 127.in-addr.arpa and 255.in-addr.arpa and any query asking for localhost.<domain>. When seeing the latter a metric counter is increased and if debug is enabled a debug log is emitted.

With local enabled any query falling under these zones will get a reply. The prevents the query from "escaping" to the internet and putting strain on external infrastructure.

The zones are mostly empty, only localhost. address records (A and AAAA) are defined and a 1.0.0.127.in-addr.arpa. reverse (PTR) record.

## SYNTAX

```
local
```

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

•

coredns_local_localhost_requests_total{} - a counter of the number of localhost.<domain> requests CoreDNS has seen. Note this does not count localhost. queries.

Note that this metric does not have a server label, because it's more interesting to find the client(s) performing these queries than to see which server handled it. You'll need to inspect the debug log to get the client IP address.

## EXAMPLES

```
. {

    local
}
```

## BUGS
Only the in-addr.arpa. reverse zone is implemented, ip6.arpa. queries are not intercepted.

## SEE ALSO
BIND9's configuration in Debian comes with these zones preconfigured. See the debug plugin for enabling debug logging.


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.