テンプレート

ソースコード

template は、着信クエリに基づいて動的な応答を可能にします。

説明

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 templateZONEがクエリ名と一致するが、正規表現と一致しない場合、次のtemplateインスタンスに続行します。次のtemplateがない場合は、次のプラグインで解決を続行します。[FALLTHROUGH-ZONE…](例:in-addr.arpaip6.arpa)がリストされている場合、それらのゾーンに対するクエリのみがフォールスルーの対象となります。fallthroughがない場合、templateZONEがクエリと一致するが正規表現と一致しない場合、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
    }
}
  1. このテンプレートは、デフォルトのゾーン(.またはすべてのクエリ)を使用します。
  2. すべてのクエリに回答されます(fallthroughなし)。
  3. 回答は常に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"
    }
}
  1. .invalidへのクエリは、NXDOMAIN(rcode)になります。
  2. キャッシングのために、ダミーのSOAレコードが送信され、TTLが60秒に設定されます。
  3. .invalidCHクラスでクエリしても、NXDOMAIN/SOA応答が返されます。
  4. デフォルトの正規表現は.*です。

無効な検索ドメインの補完をブロック

データセンター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 1034RFC 1035を参照してください。
  • テンプレート言語のリファレンスについては、Goテンプレートを参照してください。

バグ

CoreDNSは、{$ENV_VAR}という概念を持つcaddyfile環境変数をサポートしています。このパーサー機能は、{{$variable}}のようなGoテンプレート変数表記を壊します。同等の表記{{ $variable }}は機能します。このプラグインのコンテキストでは、Goテンプレート変数を避けてください。