2026年6月14日
2026年6月14日
DoQ (DNS over QUIC) と DNSSEC を併用する設定|検証をリゾルバー1か所に置き、AD・CD フラグと拡張エラーを端末まで正しく運ぶ
DoQ(DNS over QUIC)と DNSSEC を併用するときの要点は、「DNSSEC の検証はリゾルバーで行い、DoQ はその結果を端末まで安全に運ぶ」と役割を分けることです。DoQ の入口となるソフトウェアの多くは検証を行わず、問い合わせと応答を中継するだけなので、検証する場所を決めずに組み合わせると「暗号化はされているが検証されていない」状態になりがちです。この記事では、検証する場所の決め方、DNSSEC に関わるフラグ(DO・CD・AD)が DoQ を通るときの扱い、Unbound を検証役にした設定、検証が効いているかの確かめ方と、失敗したときの切り分けを説明します。
DoQ の待ち受けそのものの公開手順やアクセス制限は「DoQ を導入してセキュリティを強化する設定」の記事で、DoT と DNSSEC の組み合わせは別の記事で扱っています。ここでは DNSSEC との組み合わせで起きる問題に絞ります。
DoQ と DNSSEC の役割分担
- DoQ(RFC 9250) は、QUIC(UDP の 853 番)の上で DNS をやり取りし、端末とリゾルバーの間を暗号化します。接続先のリゾルバーが本物かどうかは証明書で確かめます。
- DNSSEC は、権威 DNS がゾーンに付けた署名を検証し、応答が改ざんされていないことを確かめます。通信の暗号化はしません。
DNSSEC の検証結果は、応答の AD(Authenticated Data)フラグで端末に伝えられます。平文の UDP で返すと、このフラグ自体を経路上で書き換えられるおそれがあるため、端末は AD フラグを信用しにくくなります。DoQ で端末とリゾルバーの間を守ると、「信頼できるリゾルバーが検証済みと言っている」ことを端末が信用できる形で受け取れます。これが併用する意味です。
検証する場所を決める
よくある構成は次の3つです。
- 自前のリゾルバーで検証し、DoQ で配る。 Unbound などで DNSSEC を検証し、その前に DoQ の入口を置きます。検証を自分の管理下に置けるため、この記事ではこの形を中心にします。
- DoQ の上流(公開リゾルバー)に検証を任せる。 端末から DoQ 対応の公開リゾルバーへ問い合わせる形です。設定は少なくて済みますが、検証するかどうかは上流の方針に依存します。
- 端末側でも検証する。 端末のスタブリゾルバーが自分で署名を検証する形です。上流を信用しなくて済む反面、DoQ に対応したクライアントで DNSSEC の検証までできるものは限られています。
注意したいのは、DoQ の入口に使われるソフトウェアの多くが検証を行わない点です。dnsdist はロードバランサーで、検証は後ろのリゾルバーに任せる設計です。AdGuard Home のように DNSSEC に関する設定を持つソフトウェアでも、自身で検証するのか、上流の検証結果を使うのかは製品と版によって異なるため、ドキュメントで確かめてください(2026年10月現在)。
検証役の Unbound を設定する
後ろに置く Unbound で DNSSEC の検証を有効にします。DoQ の入口からの問い合わせだけを受けるよう、待ち受けはローカルに絞ります。
# /etc/unbound/unbound.conf.d/validator.conf(例)
server:
interface: 127.0.0.1@5353
access-control: 127.0.0.0/8 allow
# DNSSEC の検証
module-config: "validator iterator"
auto-trust-anchor-file: "/var/lib/unbound/root.key"
# 検証に失敗した理由をログに出す
val-log-level: 2
# 失敗の理由を拡張エラー(EDE)として応答に付ける
ede: yes
auto-trust-anchor-fileはルートゾーンのトラストアンカーを自動更新する設定です。Debian・Ubuntu のパッケージでは別ファイルで設定済みのことがあるため、既存の設定と二重にならないかを確かめます。ede: yesを有効にすると、検証の失敗で SERVFAIL を返すときに「DNSSEC Bogus」などの理由(RFC 8914 の Extended DNS Errors)を応答に付けられます。DoQ の入口が応答を中継するだけなら、この情報は端末まで届き、原因の切り分けに役立ちます。対応するバージョンは手元のman unbound.confで確かめてください。
sudo unbound-checkconf
sudo systemctl restart unbound
# サーバー上で検証が効いているか
dig @127.0.0.1 -p 5353 +dnssec www.isc.org A # flags に ad が付く
dig @127.0.0.1 -p 5353 dnssec-failed.org A # SERVFAIL になる
dig @127.0.0.1 -p 5353 +cd dnssec-failed.org A # 検証を外すと応答が返る
dnssec-failed.org は検証のテストによく使われる外部のドメインのため、状態が変わる可能性があります。結果が想定と違うときは DNSViz などで現状を確かめてください。
DoQ の入口を後ろの検証役につなぐ
dnsdist を入口にする場合は、後ろのサーバーとして検証役の Unbound を指定し、DoQ の待ち受けを追加します。
-- /etc/dnsdist/dnsdist.conf の一部(例)
newServer({address = '127.0.0.1:5353'})
addDOQLocal('0.0.0.0:853', '/etc/dnsdist/tls/fullchain.pem', '/etc/dnsdist/tls/privkey.pem')
setACL({'127.0.0.0/8', '192.0.2.0/24'})
dnsdist の DoQ 対応は、ビルド時に QUIC のライブラリを組み込んでいるかに左右されます。dnsdist --version の出力で DoQ が使えるかを確かめてください。Unbound には、QUIC のライブラリを組み込んでビルドした場合に限り、DoQ で直接待ち受ける機能を持つ版があります。ディストリビューションのパッケージでは無効のことが多いため、unbound -V の出力に含まれるビルドのオプションで確かめ、使えない場合は上のように前段を置きます。
DNSSEC のフラグが入口を通るときの注意
- DO ビット。 端末が署名データ(RRSIG など)を受け取りたいときに付けるフラグです。入口がこれを落とすと、端末側では署名を見られません。中継するだけの構成なら通常はそのまま渡ります。
- CD ビット。 「検証しないで返して」という指定です。切り分けには便利ですが、端末が常に CD を付けていると、リゾルバーの検証が効かない応答を受け取ることになります。端末側の設定で意図せず付けていないかを確かめます。
- AD フラグ。 検証済みを示すフラグです。入口でキャッシュを有効にする場合は、AD・CD・DO の違いがキャッシュで区別されるかを、手元のバージョンのドキュメントで確かめます。区別されないと、検証の状態が異なる応答を取り違えるおそれがあります。
入口が検証役以外の上流(検証しない別のリゾルバー)にも振り分ける設定になっていると、問い合わせによって検証の有無が変わります。後ろのサーバーは、すべて検証するリゾルバーにそろえます。
端末から通しで確かめる
DoQ の経路を通したときに、検証の結果が端末まで届いているかを確かめます。
# Knot DNS 付属の kdig(+quic に対応した版)
# 署名されたドメイン: ad が付けば、検証済みの結果が DoQ で届いている
kdig @dns.example.com +quic +tls-ca +tls-hostname=dns.example.com +dnssec www.isc.org A
# 署名が壊れたドメイン: SERVFAIL と、EDE の理由が表示されるか
kdig @dns.example.com +quic +tls-ca +tls-hostname=dns.example.com dnssec-failed.org A
ad が付かない場合は、後ろのリゾルバーが検証していないか、入口が別の上流に振り分けているかを疑います。サーバー上で検証役に直接聞いたときに ad が付くなら、入口から後ろの経路の問題です。
うまく動かないときの切り分け
- DoQ でつながらない。 UDP の 853 番が届いていない、証明書の検証に失敗している、のどちらかが多くなります。同じサーバーで DoT(TCP 853 番)も提供しているなら、
kdig +tlsで試して TLS と証明書の問題かを分けます。QUIC は UDP のため、TCP 853 番だけを開けていても DoQ はつながりません。 - DoQ ではつながるが SERVFAIL になる。
+cdを付けて応答が返るなら DNSSEC の検証の失敗です。EDE の理由と Unbound のログ(val-log-level: 2)を見て、該当ドメインの署名や DS レコードの不整合を DNSViz で確かめます。自分のドメインなら、DS の登録ミスや鍵の更新漏れが典型例です。 - すべてのドメインで検証に失敗する。 サーバーの時刻のずれを疑います。DNSSEC の署名にも TLS の証明書にも有効期間があるため、時計がずれると DoQ の接続と検証が同時に失敗することがあります。
timedatectlで NTP の同期を確かめます。トラストアンカーのファイルが壊れていたり古かったりする場合も全滅します。 - 一部のドメインだけ失敗する。 権威 DNS 側の署名の問題か、そのドメインの DNSSEC の設定ミスであることが多く、リゾルバー側で直せない場合があります。自分の管理外のドメインで検証を一時的に外す設定(Unbound の
domain-insecureなど)は、守りを弱めるため範囲と期間を限って使います。
設定を変える前には、Unbound と dnsdist の設定ファイルを控え、可能なら検証用の環境で試してから本番に反映してください。
まとめ
- DoQ は端末とリゾルバーの間の暗号化、DNSSEC は応答の真正性の検証です。検証はリゾルバー1か所で行い、DoQ でその結果(AD フラグ)を端末まで運ぶのが基本の形です。
- DoQ の入口のソフトウェアは検証しないものが多いため、後ろのサーバーをすべて検証するリゾルバーにそろえます。
- Unbound では
validatorモジュールとトラストアンカーに加え、ede: yesで失敗の理由を端末に届けると切り分けが楽になります。 - 確認は
kdig +quic +dnssecでadフラグを見て、署名が壊れたドメインで SERVFAIL になることも確かめます。失敗時は「DoQ がつながるか」「+cdで引けるか」「時刻は正しいか」の順に分けます。