2026年6月8日

2026年6月8日

CoreDNS でACL設定する手順|acl プラグインで問い合わせ元・ゾーン・レコード種別ごとに制限する

CoreDNS で問い合わせ元を制限するには、Corefile のサーバーブロックに acl プラグインを書き、「許可するネットワークを allow で並べ、最後に block で残りを拒否する」形にするのが基本です。ACL はファイアウォールの代わりではなく、その内側でゾーンやレコード種別ごとの細かい制御を担う仕組みとして使います。この記事では、acl プラグインの書き方、目的別の設定例、動作の確かめ方、思いどおりに効かないときの確認の順番を説明します。

なぜ ACL が必要か

forward を使って再帰問い合わせを受け付ける CoreDNS を、制限なしでインターネットから届くアドレスに置くと、誰でも使える再帰サーバー(オープンリゾルバー)になります。オープンリゾルバーは、送信元を偽った問い合わせで第三者に大量の応答を送りつける攻撃(DNS アンプ攻撃)の踏み台に使われるおそれがあります。社内向けの CoreDNS でも、想定していないネットワークから社内の名前を引かれる状態は避けるべきです。

制限は次の3段階で考えると整理しやすくなります。

  1. 待ち受けるアドレスを絞る:bind プラグインで、社内側のインターフェースのアドレスだけで待ち受ける
  2. ファイアウォールで届く範囲を絞る:ufw・nftables・クラウドのセキュリティグループなどで、53番ポート(UDP と TCP)への通信を許可する送信元を限定する
  3. acl プラグインで中身に応じて絞る:ゾーンやレコード種別ごとに、許可・拒否を決める

acl プラグインは、問い合わせが CoreDNS に届いてから判断するため、届く前に止められるファイアウォールのほうが負荷の面でも有利です。ACL だけに頼らず、1と2を先に済ませておきます。

acl プラグインの書き方

基本の形は次のとおりです。

acl [ゾーン...] {
    動作 [type 種別...] [net 送信元...]
}

動作には次の4つがあります。

  • allow:許可して、次のプラグインへ処理を渡します。
  • block:拒否し、REFUSED を返します。
  • filter:答えを空にして NOERROR を返します(その種別のレコードが無いように見せる)。
  • drop:応答を返さずに捨てます。比較的新しいバージョンで追加された動作のため、使う前に手元のバージョンの説明を確認してください(2026年10月現在)。

type を省略するとすべての種別、net を省略するとすべての送信元が対象になります。ルールは上から順に評価され、最初に一致したものが適用されます。どのルールにも一致しなかった場合の扱いに頼らないよう、最後に条件なしの block を置いて「明示的に許可したもの以外は拒否」にしておくのが安全です。

なお、Corefile 内でプラグインを書く順番は実行順に影響しません。acl はビルド時に決められた順序で cache や forward より前に実行されるため、拒否された問い合わせはキャッシュも転送も行われません。

設定例1:社内ネットワークからだけ再帰問い合わせを受け付ける

もっともよく使う形です。社内のネットワークとループバックだけを許可し、それ以外を拒否します。

.:53 {
    bind 10.0.0.53 127.0.0.1
    acl {
        allow net 10.0.0.0/8 192.168.0.0/16 127.0.0.1/32
        block
    }
    forward . 10.0.0.2 10.0.0.3
    cache 300
    errors
}

net には IPv4 と IPv6 の CIDR 表記や単一のアドレスを書けます。IPv6 で待ち受ける場合は、IPv6 の社内アドレス帯の許可も忘れずに書き足してください。書き忘れると、IPv6 で届いた社内からの問い合わせがすべて拒否されます。

設定例2:ゾーンごとに許可する範囲を変える

社内向けのゾーンは特定の部署のネットワークにだけ見せ、それ以外の名前解決は広く許可したい場合は、ゾーンごとのサーバーブロックにそれぞれ acl を書きます。

secret.example.internal:53 {
    acl {
        allow net 10.20.0.0/16
        block
    }
    file /etc/coredns/db.secret.example.internal
    errors
}

.:53 {
    acl {
        allow net 10.0.0.0/8
        block
    }
    forward . 10.0.0.2
    cache 300
    errors
}

acl はそれを書いたサーバーブロックの中でだけ効きます。あるブロックに書いた制限は、別のブロックで処理される問い合わせには適用されない点に注意してください。1つのブロックの中でゾーンを分けたい場合は、acl secret.example.internal { ... } のように acl の引数でゾーンを指定する方法もあります。

設定例3:特定のレコード種別だけ制限する

レコードの種別で振る舞いを変えることもできます。

acl {
    block type ANY
    filter type AAAA net 192.168.50.0/24
    allow net 10.0.0.0/8 192.168.0.0/16
    block
}

1行目は、応答が大きくなりやすい ANY の問い合わせを誰からでも拒否します。2行目は、IPv6 の経路に問題がある特定のネットワークに対して AAAA の答えだけを空にし、端末に IPv4 を使わせる例です。filter は「レコードが存在しない」ように見せるため、一時的な回避策として使い、根本の原因(IPv6 の経路)は別に直します。

ゾーン転送(AXFR)の相手を制限したい場合は、acl ではなく transfer プラグインの to で転送を許可する相手を指定するのが本来の方法です。

動作を確かめる

設定を反映したら、許可したネットワークと許可していないネットワークの両方から問い合わせ、ヘッダーの status を確認します。

# 許可されている端末から:status: NOERROR になる
dig @10.0.0.53 www.example.com

# 許可されていない端末から:status: REFUSED になる
dig @10.0.0.53 www.example.com

複数のアドレスを持つ端末なら、dig の -b で送信元アドレスを選んで試せます。

dig -b 192.168.50.10 @10.0.0.53 www.example.com AAAA

prometheus プラグインを有効にしていれば、acl が許可・拒否した件数のメトリクスも出ます。名前はバージョンによって変わることがあるため、/metrics の出力から coredns_acl_ で始まるものを探してください。拒否の件数が急に増えた場合は、外部からの不審な問い合わせか、正規の利用者を誤って拒否しているかのどちらかなので、送信元を確認します。

思いどおりに効かないときの確認の順番

  1. ルールの順番:最初に一致したルールが適用されるため、条件なしの block を先頭に書くと、すべてが拒否されます。許可したい範囲より広い block が上にないかを確認します。
  2. CoreDNS から見える送信元アドレス:ロードバランサーや NAT、コンテナのポート公開を経由すると、CoreDNS に見える送信元が端末の本来のアドレスではなく、中継機器のアドレスになることがあります。調査中だけ log プラグインを有効にすると、記録された送信元を確認できます。Kubernetes で外部向けの Service を使う場合は、externalTrafficPolicy: Local で送信元を保つ設定が必要になることがあります。
  3. サーバーブロックの対応:問い合わせ名が、acl を書いたブロックではなく別のブロックで処理されていないかを確認します。
  4. 設定が反映されていない:reload プラグインを使っていない場合は再起動が必要です。構文の誤りがあると反映されずにエラーが出るため、ログを確認します。
  5. プラグインが含まれていない:独自にビルドした CoreDNS では、coredns -plugins の一覧に acl があるかを確認します。

Kubernetes で使うときの注意

クラスター DNS として動いている CoreDNS に acl を追加すると、Pod のアドレス範囲を許可し忘れただけでクラスター内の名前解決がすべて止まります。ConfigMap を変更する前に kubectl -n kube-system get configmap coredns -o yaml > coredns-backup.yaml でバックアップを取り、検証用のクラスターで試してから本番に反映してください。マネージド Kubernetes では、CoreDNS の設定の変更方法が独自に決められていることがあります。

問い合わせ元のネットワークによって別の答えを返したい(スプリットホライズン)場合は、拒否ではなく、view プラグインで送信元ごとにサーバーブロックを分ける方法が向いています。

まとめ

  • 待ち受けアドレスとファイアウォールで届く範囲を先に絞り、acl はその内側の細かい制御に使います。
  • acl は上から順に評価され、最初に一致したルールが適用されます。最後に条件なしの block を置きます。
  • 動作は allow・block(REFUSED)・filter(空の NOERROR)・drop(応答なし)の4つです。
  • acl は書いたサーバーブロックの中でだけ効くため、ゾーンごとの制限はブロックごとに書きます。
  • 効かないときは、ルールの順番、CoreDNS から見える送信元、ブロックの対応、反映状況の順に確認します。

お気軽にご相談ください

お見積りへ お問い合わせへ
▲