2026年6月14日
2026年6月14日
DoQ (DNS over QUIC) と DoH (DNS over HTTPS) を併用する設定|dnsdist で1台から両方を提供する構成と動作確認
DoQ と DoH は、同じリゾルバーの前に2つの入り口を並べる形で併用できます。DoH はブラウザや OS の対応が広く 443 番で通りやすいこと、DoQ は通信の遅延や再接続に強いことが利点なので、両方を用意しておくと端末ごとに合う方式を選べます。この記事では、dnsdist を入り口にして1台のサーバーから DoQ と DoH を提供する設定、ポートと証明書の設計、Web サーバーと同居させるときの注意、ポリシーをそろえる方法、動作確認までを説明します。
併用する理由と方式の違い
どちらも端末とリゾルバーの間の通信を暗号化する方式ですが、運ぶ土台が違います。
- DoH(RFC 8484) は HTTPS の上で DNS をやり取りします。通常は TCP の 443 番で、Web の通信と見分けがつきにくいため、853 番が遮断されたネットワークでも使える可能性が高い方式です。主要なブラウザや Windows などが対応しています。HTTP/3(UDP の 443 番)で運ぶ DoH3 もあります。
- DoQ(RFC 9250) は QUIC の上で DNS をやり取りし、通常は UDP の 853 番を使います。1つの問い合わせの遅れが他の問い合わせを待たせにくく、通信環境が変わったときの再接続も軽いため、モバイル回線などで利点があります。一方で、OS が標準で DoQ に対応している例はまだ少なく、主に対応アプリや DNS プロキシから使われています(2026年10月現在)。
つまり、DoH を「幅広い端末向けの標準の入り口」、DoQ を「対応した端末向けの軽い入り口」として並べるのが、併用の典型的な考え方です。どちらの入り口から来ても、後ろのリゾルバーは同じものを使います。
なお、DoQ で使う証明書や鍵の入れ替え手順は、この記事では扱いません。ここでは併用の構成に絞ります。
構成の全体像
端末(DoH) ── TCP 443 ──┐
端末(DoH3) ─ UDP 443 ──┤ dnsdist ── 127.0.0.1:5300 ── Unbound(DNSSEC 検証・キャッシュ)
端末(DoQ) ── UDP 853 ──┘
入り口に dnsdist を置くのは、DoH・DoH3・DoQ・DoT の待ち受けを1つのソフトウェアにまとめられ、アクセス制限やレート制限を共通のルールで書けるためです。後段のリゾルバーは Unbound や BIND など、普段使っているもので構いません。DoQ と DoH の待ち受けに対応しているのは dnsdist 1.9 以降で、ビルド時のオプションやパッケージによって有効な機能が異なるため、導入するパッケージの説明を確認してください。AdGuard Home や Technitium DNS Server のように、1つの製品で両方に対応しているものもあります。
事前準備
ホスト名と証明書
端末が接続先として指定するホスト名(例: dns.example.com)を1つ決め、その名前の証明書を用意します。DoQ と DoH は同じ証明書を共有できます。どちらも TLS 1.3 でハンドシェイクし、接続時の ALPN(DoQ は doq、DoH は h2 など)で方式を区別するためです。証明書は中間証明書を含む fullchain を使います。
ポートと Web サーバーとの関係
開けるポートは次のとおりです。
- TCP 443: DoH(HTTP/2)
- UDP 443: DoH3(使う場合のみ)
- UDP 853: DoQ
注意が必要なのは、WordPress などの Web サイトを動かしているサーバーに同居させる場合です。nginx や Apache がすでに 443 番を使っていると、dnsdist は同じ IP アドレスの 443 番で待ち受けられません。対処としては次のような選択肢があります。
- DNS 用に別のサーバーか、別の IP アドレスを用意する(もっとも分かりやすい方法です)。
- DoH だけ別のポート(例: 8443)で待ち受け、端末側で URL にポートを含めて指定する。ただし、ポート指定に対応していない端末もあります。
- Web サーバーをリバースプロキシにして DoH を dnsdist へ渡す。dnsdist のドキュメントにリバースプロキシ配下での設定が説明されていますが、プロキシと dnsdist の間の HTTP のバージョンなど条件があるため、該当箇所を読んでから検証環境で試します。
DNS は止まると全サービスに影響するため、Web サイトの負荷や再起動の影響を受けない 1 の構成をおすすめします。
dnsdist の設定
作業前に既存の設定ファイルをバックアップし、検証用の環境で動作を確かめてから本番へ反映します。
-- /etc/dnsdist/dnsdist.conf(例)
-- 後段のリゾルバー
newServer({address="127.0.0.1:5300", name="unbound"})
local cert = "/etc/dnsdist/tls/fullchain.pem"
local key = "/etc/dnsdist/tls/privkey.pem"
-- DoH(TCP 443、パスは /dns-query)
addDOHLocal("0.0.0.0:443", cert, key, "/dns-query")
-- DoH3(UDP 443。使う場合のみ)
addDOH3Local("0.0.0.0:443", cert, key)
-- DoQ(UDP 853)
addDOQLocal("0.0.0.0:853", cert, key)
-- 受け付ける送信元。dnsdist の既定ではプライベートアドレスなどしか許可されない
setACL({"127.0.0.0/8", "192.0.2.0/24", "198.51.100.0/24"})
-- 送信元ごとのレート制限(例: 1 秒あたり 50 件を超えたら破棄)
addAction(MaxQPSIPRule(50), DropAction())
-- 稼働中の確認用コンソール(ローカルからのみ)
controlSocket("127.0.0.1:5199")
setKey("your-console-key-base64")
設定のポイントは次のとおりです。
- ACL は全入り口に共通です。
setACLで指定した範囲は DoH・DoQ のどちらにも効きます。dnsdist は既定でプライベートアドレスとループバックなどしか受け付けないため、社外の端末から使わせる場合はここを広げる必要があります。誰でも使えるリゾルバーとして公開するかどうかは、負荷や悪用対策、ログの扱いを含めて慎重に判断します。 - ルールも全入り口に共通です。
addActionで書いたレート制限やフィルタは、どの方式で来た問い合わせにも適用されます。方式によって扱いを変えたい場合は、入り口を条件にしたルールを使います。ルールの書き方はバージョンで追加・変更があるため、ドキュメントで確認します。 - 証明書ファイルの権限。 dnsdist の実行ユーザーが秘密鍵を読めるようにし、それ以外からは読めないようにします。
setKeyの値はコンソールでmakeKey()を実行して作るものです。記事中の値はダミーです。
設定の構文を確認してから再起動します。
sudo dnsdist --check-config
sudo systemctl restart dnsdist
sudo ss -lntup | grep dnsdist
ss の出力で、TCP 443、UDP 443(DoH3 を使う場合)、UDP 853 の3つが待ち受けになっていれば起動は成功です。続けて、ファイアウォールとクラウドのセキュリティグループで同じポートを許可します。UDP の許可を忘れると、DoH は使えるのに DoQ だけつながらない状態になります。
動作を確認する
端末側から、方式ごとに問い合わせます。kdig(Knot DNS のツール)は DoH と DoQ の両方に対応しています(DoQ はバージョン 3.3 以降)。
# DoQ
kdig @dns.example.com +quic +tls-ca +tls-hostname=dns.example.com www.example.com A
# DoH(パスを指定)
kdig @dns.example.com +https=/dns-query +tls-ca +tls-hostname=dns.example.com www.example.com A
# curl の名前解決を DoH 経由にして Web ページを取得する
curl --doh-url https://dns.example.com/dns-query -sI https://www.example.com/
サーバー側では、コンソールから後段のリゾルバーの状態と統計を見られます。
sudo dnsdist -c -e 'showServers()'
sudo dnsdist -c -e 'dumpStats()'
dumpStats() には方式ごとの問い合わせ件数などの項目が含まれます(項目名はバージョンで異なります)。DoH と DoQ の両方から問い合わせたあとで、それぞれの数字が増えているかを見ると、入り口ごとの動作を確かめられます。
端末に方式を知らせる(DDR)
端末が「このリゾルバーは DoH と DoQ に対応している」と自動で知る仕組みとして、DDR(Discovery of Designated Resolvers、RFC 9462)があります。リゾルバーが _dns.resolver.arpa という名前で SVCB レコードを返し、対応方式とホスト名を伝えます。
_dns.resolver.arpa. 300 IN SVCB 1 dns.example.com. alpn=h2 dohpath=/dns-query{?dns}
_dns.resolver.arpa. 300 IN SVCB 2 dns.example.com. alpn=doq
DDR を使って自動で暗号化 DNS に切り替える端末はまだ一部で、どの方式を選ぶかも端末によって違います。dnsdist や後段のリゾルバーで返す方法はソフトウェアごとに異なるため、導入する場合はそれぞれのドキュメントを確認してください。DDR を使わない場合は、端末ごとにホスト名と URL を手動で設定します。
運用で気を付けること
- ログと個人情報。 問い合わせログには、誰がどのサイトを見たかに近い情報が含まれます。社外の利用者に提供する場合は、保存期間と利用目的を決め、プライバシーポリシーに記載します。必要がなければ送信元 IP アドレスを長く残さない設定にします。
- 片方だけ止まる障害。 DoH は TCP、DoQ は UDP なので、ネットワーク側の変更で片方だけ通らなくなることがあります。監視は方式ごとに分けて行い、
kdig +quicとkdig +httpsを定期的に実行して応答を確かめるとよいです。 - 端末側のフォールバック。 端末によっては、暗号化 DNS が使えないと平文の DNS へ戻ります。戻らせたくない場合は、端末側の設定で「暗号化 DNS のみ」を選べるか確認します。
まとめ
- DoH は対応端末が多く 443 番で通りやすい入り口、DoQ は遅延や再接続に強い入り口です。同じリゾルバーの前に両方を並べて併用します。
- dnsdist では
addDOHLocal・addDOH3Local・addDOQLocalで待ち受けを作り、同じホスト名の証明書を共有できます。 - ACL やレート制限は全入り口に共通なので、まとめて管理できます。既定の ACL はプライベートアドレス中心である点に注意します。
- Web サーバーと同じ IP アドレスでは 443 番が競合するため、DNS 用の IP アドレスかサーバーを分けるのが分かりやすい構成です。
- 確認は
kdig +quicとkdig +https、curl --doh-urlで方式ごとに行い、監視も方式ごとに分けます。