2026年6月4日
2026年6月4日
TinyDNS のACL設定方法|axfrdns の tcp ルール・dnscache の ip ディレクトリ・ロケーションで「誰に答えるか」を決める
TinyDNS(djbdns の権威DNS)には、BIND の allow-query や allow-transfer のような ACL の設定項目がありません。アクセスを制御する場所は役割ごとに分かれていて、ゾーン転送は axfrdns の tcp ファイル、キャッシュサーバーの利用者は dnscache の root/ip ディレクトリ、問い合わせ元による答えの出し分けは data ファイルのロケーション、それ以外の「そもそも誰の問い合わせを受けるか」はファイアウォールで決めます。この記事では、それぞれの書き方と確認方法、よくあるつまずきを順に説明します。
djbdns 本体は 1.05 以降、作者による公式な更新がなく、IPv6 対応などはディストリビューションのパッチ版に頼っている状態です(2026年10月現在)。以下は IPv4 を前提にした説明で、パッチ版ではロケーションの書き方などが拡張されていることがあります。手元の版の説明書きと照らし合わせてください。
どこで何を制御するかを先に整理する
djbdns は役割ごとにプログラムが分かれているため、「何を制限したいか」によって設定する場所が違います。
- ゾーン転送(AXFR)を誰に許すか:axfrdns の
tcpファイル。BIND のallow-transferに当たります。 - キャッシュサーバー(再帰問い合わせ)を誰に使わせるか:dnscache の
root/ipディレクトリ。BIND のallow-recursionに当たります。 - 問い合わせ元によって違う答えを返すか:tinydns の data ファイルのロケーション(
%の行)。BIND の view に近い使い方ができます。 - tinydns そのものに誰が問い合わせられるか:tinydns には問い合わせ元を拒否する設定がないため、待ち受けるアドレス(
env/IP)とファイアウォールで制御します。
インターネットに公開する権威サーバーは、本来だれからの問い合わせにも答えるものです。tinydns は再帰問い合わせを行わず、自分が持つゾーンにしか答えないため、公開しても「オープンリゾルバー」にはなりません。制限が必要になるのは、主に社内専用のゾーンを持つ場合、ゾーン転送、キャッシュサーバーの3つです。
axfrdns の tcp ファイルでゾーン転送を制限する
tinydns は UDP でしか答えません。TCP の問い合わせとゾーン転送は axfrdns が受け持ち、axfrdns は tcpserver(ucspi-tcp)の下で動きます。誰の接続を受けるか、どのゾーンの転送を許すかは、サービスディレクトリの tcp ファイルに tcprules の書式で書きます。
# /etc/axfrdns/tcp(ディレクトリは環境に合わせて読み替え)
# セカンダリには example.com と example.net の転送を許可する
198.51.100.53:allow,AXFR="example.com/example.net"
# それ以外は TCP の通常の問い合わせだけ受け、転送は許可しない
:allow,AXFR=""
cd /etc/axfrdns
sudo make # tcp から tcp.cdb を作る
AXFR 環境変数には転送を許すゾーンをスラッシュ区切りで書きます。AXFR を指定しない行は「すべてのゾーンの転送を許可する」という意味になるので、セカンダリ以外の行には AXFR="" を付けて転送を禁止します。
最後の行を :deny にすると、セカンダリ以外からの TCP の問い合わせをすべて断ることになります。DNS では応答が大きい場合(多くの TXT や DNSSEC 関連のレコードなど)に、リゾルバーが TCP で問い合わせ直します。公開する権威サーバーで TCP を閉じると、そうした名前だけ解決できなくなるため、転送の制限と TCP の問い合わせの受け付けは分けて考えます。
tcp は make で tcp.cdb に変換されてから使われます。tcpserver は接続のたびに tcp.cdb を読むので、axfrdns の再起動は要りません。逆に、tcp を編集しただけで make を忘れると、何も変わりません。
転送の制限を確認する
# 許可したセカンダリ(198.51.100.53)から実行:レコードが全件表示されれば成功
dig @192.0.2.53 example.com AXFR
# 許可していないホストから実行:転送が失敗することを確かめる
dig @192.0.2.53 example.com AXFR
許可していないホストで Transfer failed. などと表示されれば、制限は効いています。転送できてしまう場合は、AXFR を付けていない行が先にマッチしていないかを見ます。tcprules は上から順に、最初に一致した行を使います。
dnscache の root/ip でキャッシュサーバーの利用者を絞る
dnscache は、root/ip ディレクトリに置いたファイルの名前で、問い合わせを受ける相手を決めます。ファイルの中身は空でかまいません。dnscache-conf で作った直後は 127.0.0.1 だけが許可されています。
cd /etc/dnscache/root/ip # 環境に合わせて読み替え
ls # 127.0.0.1 だけがあるはず
# 192.168.1.0/24 からの問い合わせを許可する
sudo touch 192.168.1
# 10.0.0.0/8 全体を許可する
sudo touch 10
ファイル名は IP アドレスの先頭から「ドット区切りの単位」で一致させる仕組みです。192.168.1 は 192.168.1.0〜192.168.1.255 に一致しますが、/23 や /20 のような途中のビットでの区切りは書けません。必要なら単位ごとに複数のファイルを置きます。
あわせて、dnscache がどのアドレスで待ち受けるかを env/IP で確認します。社内向けなら社内のアドレスにし、インターネット側のアドレスでは待ち受けません。
cat /etc/dnscache/env/IP
# 変更したら dnscache を再起動する
sudo svc -t /service/dnscache
root/ip に許可していない相手からの問い合わせには、dnscache は答えません(クライアントからはタイムアウトに見えます)。インターネット全体を許可したキャッシュサーバーは、DNS の増幅攻撃の踏み台に使われるおそれがあるため、root/ip に 0 のような広すぎる名前のファイルを置かないでください。
ロケーションで問い合わせ元ごとに答えを変える
tinydns の data ファイルでは、% の行で「この IP アドレスで始まる問い合わせ元はこの場所」と定義し、各レコードの最後の欄に場所の名前を書くことで、その場所からの問い合わせにだけ見せるレコードを作れます。
# 場所の定義:in = 社内、ex = それ以外(空の接頭辞はすべてに一致)
%in:192.168
%in:10
%ex
# 社内からは社内のアドレス、それ以外からは公開のアドレスを返す
+www.example.com:192.168.1.10:300::in
+www.example.com:192.0.2.10:300::ex
# 社内だけに見せる名前
+intranet.example.com:192.168.1.20:300::in
# 場所を付けないレコードは、だれにでも見える
@example.com::mail.example.com:10:3600
cd /etc/tinydns/root
sudo make # data から data.cdb を作る。tinydns の再起動は要らない
書式は「+名前:IPアドレス:TTL:タイムスタンプ:場所」で、タイムスタンプを使わない場合は空欄にします。場所の名前は1〜2文字の英字です。問い合わせ元が複数の定義に当てはまる場合は、より長い接頭辞が優先されるとされていますが、意図した場所に振り分けられているかは、次の確認で実際に確かめてください。
ロケーションは「答えを出し分ける」機能で、「問い合わせを拒否する」機能ではありません。社内専用の名前も、外部から問い合わせが届くこと自体は防げず、存在しないものとして扱われるか空の応答になるかは構成によって変わります。社内の情報を外に出したくないなら、社内用の tinydns を別のアドレスで動かし、ファイアウォールで外部から届かないようにするほうが分かりやすく、間違いも起きにくくなります。
出し分けを確認する
# 社内のホストから
dig @192.0.2.53 www.example.com A +norec +short
# 社外のホスト(または社外向けの経路)から
dig @192.0.2.53 www.example.com A +norec +short
dig @192.0.2.53 intranet.example.com A +norec
社内からは 192.168.1.10、社外からは 192.0.2.10 が返り、社外から intranet の名前を引いたときにアドレスが返らなければ想定どおりです。キャッシュサーバーを経由すると、キャッシュサーバーのアドレスで場所が判定される点に注意します。社内の dnscache が問い合わせると、社内の利用者にはすべて in の答えが返ります。
tinydns への問い合わせ自体をファイアウォールで制限する
社内専用の tinydns のように、特定のネットワークからしか問い合わせを受けたくない場合は、ファイアウォールで UDP の53番ポートを絞ります。次は nftables の例で、既存のルールとは別のテーブルを作り、53番ポートだけを対象にしています。
# /etc/nftables.d/tinydns-acl.nft(読み込み方法は環境に合わせる)
table inet tinydns_acl {
set allowed_v4 {
type ipv4_addr
flags interval
elements = { 192.168.0.0/16, 10.0.0.0/8 }
}
chain input {
type filter hook input priority 0; policy accept;
ip daddr 192.168.1.53 udp dport 53 ip saddr @allowed_v4 accept
ip daddr 192.168.1.53 udp dport 53 drop
ip daddr 192.168.1.53 tcp dport 53 ip saddr @allowed_v4 accept
ip daddr 192.168.1.53 tcp dport 53 drop
}
}
sudo nft -c -f /etc/nftables.d/tinydns-acl.nft # 文法だけ確認する
sudo nft -f /etc/nftables.d/tinydns-acl.nft
sudo nft list table inet tinydns_acl
チェーンの既定の方針を accept にし、宛先アドレスと53番ポートに絞って書いているため、SSH などほかの通信には影響しません。リモートで作業する場合でも、適用前に -c で文法を確かめ、問題があればテーブルを nft delete table inet tinydns_acl で消せることを覚えておくと安心です。すでに firewalld や ufw で管理している環境では、そのツールの書き方に合わせてください。
tinydns には応答の回数を抑える機能(RRL)もありません。公開する権威サーバーで大量の問い合わせが問題になる場合は、ファイアウォールの流量制限や、上流の DDoS 対策サービスを検討します。
よくあるつまずき
- **
makeを忘れる**:tcpもdataも、makeで.cdbを作り直すまで反映されません。編集したらmakeを実行し、エラーが出ていないことを確認します。makeが失敗した場合、古い.cdbのまま動き続けるので、気づきにくい点に注意します。 - **
AXFRを付け忘れた行がある**:AXFRのないallowの行は、全ゾーンの転送を許可します。 - TCP を全部閉じてしまう:転送を止めたいだけなのに
:denyにすると、大きな応答を TCP で取りに来るリゾルバーが失敗します。 - dnscache の許可がネットワーク単位でしか書けない:
192.168.1のようなドット単位の接頭辞なので、細かい範囲はファイアウォール側で絞ります。 - ロケーションの判定がキャッシュサーバーのアドレスで行われる:利用者ではなく、tinydns に問い合わせてきたキャッシュサーバーのアドレスで場所が決まります。
設定を変える前には、data・tcp・root/ip の中身をコピーしておき、可能なら検証用のサーバーで同じ変更を試してから本番に反映します。
まとめ
- TinyDNS には BIND のような ACL の設定項目がなく、制御する場所が役割ごとに分かれています。
- ゾーン転送は axfrdns の
tcpファイルで許可し、セカンダリ以外の行にはAXFR=""を付けます。TCP の問い合わせそのものは閉じないようにします。 - dnscache の利用者は
root/ipのファイル名で許可し、広すぎる範囲を許可しないようにします。 - ロケーションは答えの出し分けで、拒否の仕組みではありません。社内専用のゾーンは別のアドレスとファイアウォールで守ります。