|
NAMEtemplate - allows for dynamic responses based on the incoming query.DESCRIPTIONThe template plugin allows you to dynamically respond to queries by just writing a (Go) template.SYNTAXtemplate CLASS TYPE [ZONE...] { match REGEX... answer RR additional RR authority RR rcode CODE fallthrough [ZONE...] }
At least one answer or rcode directive is needed (e.g. rcode NXDOMAIN). Also see ⟨#also-see⟩ contains an additional reading list. TEMPLATESEach resource record is a full-featured Go template ⟨https://golang.org/pkg/text/template/⟩ with the following predefined data
The output of the template must be a RFC 1035 ⟨https://tools.ietf.org/html/rfc1035⟩ style resource record (commonly referred to as a "zone file"). WARNING there is a syntactical problem with Go templates and CoreDNS config files. Expressions like {{$var}} will be interpreted as a reference to an environment variable by CoreDNS (and Caddy) while {{ $var }} will work. See Bugs ⟨#bugs⟩ and corefile(5). METRICSIf monitoring is enabled (via the prometheus plugin) then the following metrics are exported:
Both failure cases indicate a problem with the template configuration. The server label indicates the server incrementing the metric, see the metrics plugin for details. EXAMPLESRESOLVE EVERYTHING TO NXDOMAINThe most simplistic template is. { template ANY ANY { rcode NXDOMAIN } }
RESOLVE .INVALID AS NXDOMAINThe .invalid domain is a reserved TLD (see RFC 2606 Reserved Top Level DNS Names ⟨https://tools.ietf.org/html/rfc2606#section-2⟩) to indicate invalid domains.. { forward . 8.8.8.8 template ANY ANY invalid { rcode NXDOMAIN authority "invalid. 60 {{ .Class }} SOA ns.invalid. hostmaster.invalid. (1 60 60 60 60)" } }
BLOCK INVALID SEARCH DOMAIN COMPLETIONSImagine you run example.com with a datacenter dc1.example.com. The datacenter domain is part of the DNS search domain. However something.example.com.dc1.example.com would indicate a fully qualified domain name (something.example.com) that inadvertently has the default domain or search path (dc1.example.com) added.. { forward . 8.8.8.8 template IN ANY example.com.dc1.example.com { rcode NXDOMAIN authority "{{ .Zone }} 60 IN SOA ns.example.com hostmaster.example.com (1 60 60 60 60)" } } A more verbose regex based equivalent would be . { forward . 8.8.8.8 template IN ANY example.com { match "example\.com\.(dc1\.example\.com\.)$" rcode NXDOMAIN authority "{{ index .Match 1 }} 60 IN SOA ns.{{ index .Match 1 }} hostmaster.{{ index .Match 1 }} (1 60 60 60 60)" fallthrough } } The regex-based version can do more complex matching/templating while zone-based templating is easier to read and use. RESOLVE A/PTR FOR .EXAMPLE. { forward . 8.8.8.8 # ip-a-b-c-d.example A a.b.c.d template IN A example { match (^|[.])ip-(?P<a>[0-9]*)-(?P<b>[0-9]*)-(?P<c>[0-9]*)-(?P<d>[0-9]*)[.]example[.]$ answer "{{ .Name }} 60 IN A {{ .Group.a }}.{{ .Group.b }}.{{ .Group.c }}.{{ .Group.d }}" fallthrough } # d.c.b.a.in-addr.arpa PTR ip-a-b-c-d.example template IN PTR in-addr.arpa { match ^(?P<d>[0-9]*)[.](?P<c>[0-9]*)[.](?P<b>[0-9]*)[.](?P<a>[0-9]*)[.]in-addr[.]arpa[.]$ answer "{{ .Name }} 60 IN PTR ip-{{ .Group.a }}-{{ .Group.b }}-{{ .Group.c }}-{{ .Group.d }}.example." } } An IPv4 address consists of 4 bytes, a.b.c.d. Named groups make it less error-prone to reverse the IP address in the PTR case. Try to use named groups to explain what your regex and template are doing. Note that the A record is actually a wildcard: any subdomain of the IP address will resolve to the IP address. Having templates to map certain PTR/A pairs is a common pattern. Fallthrough is needed for mixed domains where only some responses are templated. RESOLVE MULTIPLE IP PATTERNS. { forward . 8.8.8.8 template IN A example { match "^ip-(?P<a>10)-(?P<b>[0-9]*)-(?P<c>[0-9]*)-(?P<d>[0-9]*)[.]dc[.]example[.]$" match "^(?P<a>[0-9]*)[.](?P<b>[0-9]*)[.](?P<c>[0-9]*)[.](?P<d>[0-9]*)[.]ext[.]example[.]$" answer "{{ .Name }} 60 IN A {{ .Group.a}}.{{ .Group.b }}.{{ .Group.c }}.{{ .Group.d }}" fallthrough } } Named capture groups can be used to template one response for multiple patterns. RESOLVE A AND MX RECORDS FOR IP TEMPLATES IN .EXAMPLE. { forward . 8.8.8.8 template IN A example { match ^ip-10-(?P<b>[0-9]*)-(?P<c>[0-9]*)-(?P<d>[0-9]*)[.]example[.]$ answer "{{ .Name }} 60 IN A 10.{{ .Group.b }}.{{ .Group.c }}.{{ .Group.d }}" fallthrough } template IN MX example { match ^ip-10-(?P<b>[0-9]*)-(?P<c>[0-9]*)-(?P<d>[0-9]*)[.]example[.]$ answer "{{ .Name }} 60 IN MX 10 {{ .Name }}" additional "{{ .Name }} 60 IN A 10.{{ .Group.b }}.{{ .Group.c }}.{{ .Group.d }}" fallthrough } } ADDING AUTHORITATIVE NAMESERVERS TO THE RESPONSE. { forward . 8.8.8.8 template IN A example { match ^ip-10-(?P<b>[0-9]*)-(?P<c>[0-9]*)-(?P<d>[0-9]*)[.]example[.]$ answer "{{ .Name }} 60 IN A 10.{{ .Group.b }}.{{ .Group.c }}.{{ .Group.d }}" authority "example. 60 IN NS ns0.example." authority "example. 60 IN NS ns1.example." additional "ns0.example. 60 IN A 203.0.113.8" additional "ns1.example. 60 IN A 198.51.100.8" fallthrough } template IN MX example { match ^ip-10-(?P<b>[0-9]*)-(?P<c>[0-9]*)-(?P<d>[0-9]*)[.]example[.]$ answer "{{ .Name }} 60 IN MX 10 {{ .Name }}" additional "{{ .Name }} 60 IN A 10.{{ .Group.b }}.{{ .Group.c }}.{{ .Group.d }}" authority "example. 60 IN NS ns0.example." authority "example. 60 IN NS ns1.example." additional "ns0.example. 60 IN A 203.0.113.8" additional "ns1.example. 60 IN A 198.51.100.8" fallthrough } } ALSO SEE
BUGSCoreDNS supports caddyfile environment variables ⟨https://caddyserver.com/docs/caddyfile#env⟩ with notion of {$ENV_VAR}. This parser feature will break Go template variables ⟨https://golang.org/pkg/text/template/#hdr-Variables⟩ notations like{{$variable}}. The equivalent notation {{ $variable }} will work. Try to avoid Go template variables in the context of this plugin.
Visit the GSP FreeBSD Man Page Interface. |