説明
template プラグインを使用すると、(Go)テンプレートを記述するだけで、クエリに動的に応答できます。
構文
template CLASS TYPE [ZONE...] {
match REGEX...
answer RR
additional RR
authority RR
rcode CODE
ederror EXTENDED_ERROR_CODE [EXTRA_REASON]
fallthrough [FALLTHROUGH-ZONE...]
}
- CLASS クエリクラス(通常は IN または ANY)。
- TYPE クエリタイプ(A、PTR… すべての種類に一致させるには ANY を使用できます)。
- ZONE このテンプレートのゾーンスコープ。デフォルトはサーバーゾーンです。
match
REGEX 着信クエリ名と照合されるGo正規表現。正規表現を指定しないとすべてに一致します(デフォルト:.*
)。最初に一致した正規表現が優先されます。answer|additional|authority
RR RFC 1035 スタイルのリソースレコードフラグメント。これは、応答を含むGoテンプレートによって構築されます。answer を指定しないと、回答セクションが空の応答が返されます。rcode
CODE 応答コード(NXDOMAIN、SERVFAIL、...
)。デフォルトはNOERROR
です。有効な応答コードの値は、miekg/dns
パッケージのmsg.go
で定義されているRcodeToString
マップに従います。ederror
EXTENDED_ERROR_CODE は、RFC8914
で定義されている拡張DNSエラーコードの数値です(0、1、2…、24)。EXTRA_REASON は、エラーを返す理由を説明する追加の文字列です。fallthrough
templateのZONEがクエリ名と一致するが、正規表現と一致しない場合、次のtemplateインスタンスに続行します。次のtemplateがない場合は、次のプラグインで解決を続行します。[FALLTHROUGH-ZONE…](例:in-addr.arpa
とip6.arpa
)がリストされている場合、それらのゾーンに対するクエリのみがフォールスルーの対象となります。fallthrough
がない場合、templateのZONEがクエリと一致するが正規表現と一致しない場合、SERVFAIL
応答が返されます。
こちらも参照してくださいには、追加の読書リストが含まれています。
テンプレート
各リソースレコードは、次の事前定義データを持つ、フル機能のGoテンプレートです。
.Zone
一致したゾーン文字列(例:example.
)。.Name
クエリ名(小文字)。.Class
クエリクラス(通常はIN
)。.Type
要求されたRRタイプ(例:PTR
)。.Match
すべてのマッチの配列。index .Match 0
は、完全一致を参照します。.Group
名前付きキャプチャグループのマップ。.Message
完全な着信DNSメッセージ。.Question
一致した質問セクション。.Remote
クライアントのIPアドレス。.Meta
メタデータ名を受け取り、メタデータプラグインが有効になっている場合に値を返す関数。例:.Meta "kubernetes/client-namespace"
および、次の事前定義テンプレート関数
parseInt
指定された基数とビットサイズで文字列を解釈します。strconv.ParseUintと同等です。
テンプレートの出力は、RFC 1035スタイルのリソースレコード(一般的に「ゾーンファイル」と呼ばれます)である必要があります。
警告 GoテンプレートとCoreDNS設定ファイルには、構文上の問題があります。{{$var}}
のような式は、CoreDNS(およびCaddy)によって環境変数の参照として解釈されますが、{{ $var }}
は機能します。バグとcorefile(5)を参照してください。
メトリクス
モニタリングが有効になっている場合(prometheusプラグイン経由)、次のメトリクスがエクスポートされます。
coredns_template_matches_total{server, zone, view, class, type}
正規表現によって一致したリクエストの総数。coredns_template_template_failures_total{server, zone, view, class, type, section, template}
Goテンプレート処理が失敗した回数。正規表現、セクション、テンプレートのラベル値を使用して、エラーを設定ファイルにマッピングできます。coredns_template_rr_failures_total{server, zone, view, class, type, section, template}
テンプレート化されたリソースレコードが無効で、解析できなかった回数。正規表現、セクション、テンプレートのラベル値を使用して、エラーを設定ファイルにマッピングできます。
どちらの失敗ケースも、テンプレート設定の問題を示しています。server
ラベルは、メトリクスを増分するサーバーを示しています。詳細については、metricsプラグインを参照してください。
例
すべてをNXDOMAINに解決
最も単純なテンプレートは次のとおりです。
. {
template ANY ANY {
rcode NXDOMAIN
}
}
- このテンプレートは、デフォルトのゾーン(
.
またはすべてのクエリ)を使用します。 - すべてのクエリに回答されます(
fallthrough
なし)。 - 回答は常にNXDOMAINです。
.invalidをNXDOMAINに解決
.invalid
ドメインは、無効なドメインを示す予約済みTLDです(RFC 2606 Reserved Top Level DNS Namesを参照)。
. {
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)"
ederror 21 "Blocked according to RFC2606"
}
}
- .invalidへのクエリは、NXDOMAIN(rcode)になります。
- キャッシングのために、ダミーのSOAレコードが送信され、TTLが60秒に設定されます。
.invalid
をCH
クラスでクエリしても、NXDOMAIN/SOA応答が返されます。- デフォルトの正規表現は
.*
です。
無効な検索ドメインの補完をブロック
データセンターdc1.example.com
を持つexample.com
を実行しているとします。データセンタードメインは、DNS検索ドメインの一部です。しかし、something.example.com.dc1.example.com
は、デフォルトドメインまたは検索パス(dc1.example.com
)が不注意に追加された完全修飾ドメイン名(something.example.com
)を示しています。
. {
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)"
}
}
より詳細な正規表現ベースの同等物は次のとおりです。
. {
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
}
}
正規表現ベースのバージョンでは、より複雑な照合/テンプレート処理を実行できますが、ゾーンベースのテンプレート処理の方が読みやすく、使いやすくなっています。
.exampleのA/PTRを解決
. {
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."
}
}
IPv4アドレスは4バイト(a.b.c.d
)で構成されます。名前付きグループを使用すると、PTRの場合にIPアドレスを逆順にする際のエラーを少なくできます。名前付きグループを使用して、正規表現とテンプレートの機能を説明してみてください。
Aレコードは実際にはワイルドカードであることに注意してください。IPアドレスの任意のサブドメインが、そのIPアドレスに解決されます。
特定のPTR/Aペアをマッピングするテンプレートを持つことは、一般的なパターンです。
応答の一部のみがテンプレート化されている混合ドメインでは、フォールスルーが必要です。
parseIntを使用して16進数のIPパターンを解決
. {
forward . 8.8.8.8
template IN A example {
match "^ip0a(?P<b>[a-f0-9]{2})(?P<c>[a-f0-9]{2})(?P<d>[a-f0-9]{2})[.]example[.]$"
answer "{{ .Name }} 60 IN A 10.{{ parseInt .Group.b 16 8 }}.{{ parseInt .Group.c 16 8 }}.{{ parseInt .Group.d 16 8 }}"
fallthrough
}
}
IPv4アドレスは、16進数エンコーディングを使用して、よりコンパクトな形式で表現できます。たとえば、ip-10-123-123.example.
は、ip0a7b7b7b.example.
として表現できます。
複数のIPパターンを解決
. {
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
}
}
名前付きキャプチャグループを使用して、複数のパターンに対して1つの応答をテンプレート化できます。
.exampleのIPテンプレートに対してAレコードとMXレコードを解決
. {
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
}
}
応答に権威のあるネームサーバーを追加
. {
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
}
}
CNAMEを作成
この例では、foogle.com
に対して正確に行われたDNSクエリに対して、google.com
へのCNAMEで応答します。アップストリームネームサーバーが要求されたタイプのレコードを返すことができる場合、回答にはgoogle.com
のレコードも含まれます。
. {
template IN ANY foogle.com {
match "^foogle\.com\.$"
answer "foogle.com 60 IN CNAME google.com"
}
forward . 8.8.8.8
}
こちらも参照してください
- 正規表現の実装の詳細については、Go正規表現を参照してください。
- 正規表現構文の詳細については、RE2構文リファレンスを参照してください。
- リソースレコード形式については、RFC 1034とRFC 1035を参照してください。
- テンプレート言語のリファレンスについては、Goテンプレートを参照してください。
バグ
CoreDNSは、{$ENV_VAR}
という概念を持つcaddyfile環境変数をサポートしています。このパーサー機能は、{{$variable}}
のようなGoテンプレート変数表記を壊します。同等の表記{{ $variable }}
は機能します。このプラグインのコンテキストでは、Goテンプレート変数を避けてください。