DD-WRT の Unbound 有効化でハマった話(あるいはDNSSECの罠)

技術ネタ

自宅のWireGuard VPNエンドポイントとしてよく使ってるDD-WRTルータですが、前から気になっていたUnbound(フルリゾルバ)の有効化にチャレンジしたところハマったので、次にセットアップするときの備忘録的に記録しておきます。

設定項目

設定項目はとてもシンプルで、以下の「Setup>Recursive DNS Resolving (Unbound)」にチェックを入れて「Apply Setting」するだけなのですが…

実はこれは、「Unboundをポート7053で起動し、DNSMasqがDNSクエリを投げる先をlocalhost(127.0.0.1)の7053番ポートに変更する」という設定をすることになるのです。つまり、PCやDD-WRTルータ自身は相変わらず「DD-WRTルータのUDPポート53番」にDNSクエリを送信し、それに対する直接の応答もDNSMasqが行っているのです。関連するコンフィグを抜粋します。

■DNSMasqの設定
# cat /tmp/dnsmasq.conf | grep server
server=127.0.0.1#7053

■Unboundの設定
# cat /tmp/unbound.conf | grep interface
interface: 0.0.0.0@7053

なにが問題なのか

実はDD-WRTルータのUnbound設定は「デフォルトでDNSSEC有効」な設定になっています。

# cat /tmp/unbound.conf | grep trust
auto-trust-anchor-file: "/etc/unbound/root.key"

そうすると、ルータ起動時(=Unboundの起動時)に、RTCを持っていないルータでシステム時刻が「2000年1月1日 AM9:00」のような時間になっていると、DNSSECを含む「フルリゾルバとしてのUnbound」が正常に動作しなくなります。

RTC(Real Time Clock)

電池などを使って、システムが停止している間も現在時刻を維持し続ける内部時計のこと。詳細は Wikipediaの「リアルタイムクロック」 などを見てみてください。

理由については、以下のPDFのトラブル事例の初っ端に記載されています。
DNSハンズオン DNS運⽤のいろは「DNSSEC トラブルシュート編」

この事象が発生している場合、以下のようなログが /var/log/messages に記録されます。

Jan  1 09:00:23 ddwrt-router user.info : unbound : recursive dns resolver daemon successfully started
Jan  1 09:00:23 ddwrt-router daemon.notice unbound: [1440:0] notice: init module 0: validator
Jan  1 09:00:23 ddwrt-router daemon.notice unbound: [1440:0] notice: init module 1: iterator
Jan  1 09:00:23 ddwrt-router daemon.info unbound: [1440:0] info: start of service (unbound 1.13.1).
Jan  1 09:00:23 ddwrt-router daemon.info unbound: [1440:0] info: generate keytag query _ta-4a5c-4f66. NULL IN
Jan  1 09:00:23 ddwrt-router daemon.info unbound: [1440:0] info: failed to prime trust anchor -- DNSKEY rrset is not secure . DNSKEY IN
Jan  1 09:00:23 ddwrt-router daemon.info unbound: [1440:0] info: generate keytag query _ta-4a5c-4f66. NULL IN
Jan  1 09:00:23 ddwrt-router daemon.info unbound: [1440:0] info: failed to prime trust anchor -- DNSKEY rrset is not secure . DNSKEY IN
Jan  1 09:00:23 ddwrt-router daemon.info unbound: [1440:0] info: generate keytag query _ta-4a5c-4f66. NULL IN
Jan  1 09:00:24 ddwrt-router daemon.info unbound: [1440:0] info: failed to prime trust anchor -- DNSKEY rrset is not secure . DNSKEY IN
Jan  1 09:00:24 ddwrt-router daemon.info unbound: [1440:0] info: failed to prime trust anchor -- DNSKEY rrset is not secure . DNSKEY IN
Jan  1 09:00:24 ddwrt-router daemon.info unbound: [1440:0] info: generate keytag query _ta-4a5c-4f66. NULL IN
Jan  1 09:00:24 ddwrt-router daemon.info unbound: [1440:0] info: failed to prime trust anchor -- DNSKEY rrset is not secure . DNSKEY IN
Jan  1 09:00:24 ddwrt-router daemon.info unbound: [1440:0] info: failed to prime trust anchor -- DNSKEY rrset is not secure . DNSKEY IN

こうなってしまうと、時刻が正しくセットされるまでUnboundはDNSクエリを受け付けなくなってしまいます。名前解決のためのDNSクエリを受け付けないということは、FQDNを使ったNTPによる時刻同期設定をしていたとしても、名前解決が成功しないためいつまでたっても時刻同期は成功しない事になり、時刻が正しくセットされないのでDNSMasq→Unboundに渡される名前解決処理もいつまでたっても成功しない、ということになります。

つまりどういうこと?

DD-WRTのUnboundを有効にすると「RTCを持たない機器ではいつまでもDNSによる名前解決が利用できない」状況になります。「DNSMasq→プロバイダ提供のフルリゾルバへ転送」ではなく宅内の機器でフルリゾルバを動かしたいという目的のために有効化したはずのUnboundが、DNSSECがデフォルト有効なせいでシステム時刻不正が起因で名前解決ができないためにシステム時刻の同期ができないという、まさに「鶏と卵」な状態になってしまうのです。

解決策は?

DD-WRTでは、特定の場所に配置したスクリプトを起動中の特定のタイミングで実行する仕組みがあります。

今回はこの仕組みを使って、 .prewall なスクリプトで「起動時に ntpclient コマンドでIPアドレスを指定して時刻同期をする」ことにしました。具体的にはこんなスクリプトを実行させます。

#!/bin/sh
/usr/sbin/ntpclient 210.173.160.27

210.173.160.27 は、ntp.jst.mfeed.ad.jp の持つアドレスのうちの一つです。

$ host ntp.jst.mfeed.ad.jp
ntp.jst.mfeed.ad.jp has address 210.173.160.27
ntp.jst.mfeed.ad.jp has address 210.173.160.87
ntp.jst.mfeed.ad.jp has address 210.173.160.57

このスクリプトによって時刻同期が完了すると、Unboundが再起動して正常にDNSクエリを受け付けるようになります。

Jan  1 09:00:24 ddwrt-router daemon.info unbound: [1440:0] info: failed to prime trust anchor -- DNSKEY rrset is not secure . DNSKEY IN
Mar  3 13:57:41 ddwrt-router daemon.info unbound: [1440:0] info: generate keytag query _ta-4a5c-4f66. NULL IN
Mar  3 13:57:41 ddwrt-router user.info : unbound : daemon successfully stopped
Mar  3 13:57:41 ddwrt-router daemon.info unbound: [1440:0] info: service stopped (unbound 1.13.1).
Mar  3 13:57:41 ddwrt-router daemon.info unbound: [1440:0] info: server stats for thread 0: 1 queries, 0 answers from cache, 1 recursions, 0 prefetch, 0 rejected by ip ratelimiting
Mar  3 13:57:41 ddwrt-router daemon.info unbound: [1440:0] info: server stats for thread 0: requestlist max 0 avg 0 exceeded 0 jostled 0
Mar  3 13:57:41 ddwrt-router daemon.info unbound: [1440:0] info: average recursion processing time 1.119868 sec
Mar  3 13:57:41 ddwrt-router daemon.info unbound: [1440:0] info: histogram of recursion processing times
Mar  3 13:57:41 ddwrt-router daemon.info unbound: [1440:0] info: [25%]=0 median[50%]=0 [75%]=0
Mar  3 13:57:41 ddwrt-router daemon.info unbound: [1440:0] info: lower(secs) upper(secs) recursions
Mar  3 13:57:41 ddwrt-router daemon.info unbound: [1440:0] info:    1.000000    2.000000 1
Mar  3 13:57:41 ddwrt-router daemon.info unbound: [1440:0] info: server stats for thread 1: 4 queries, 0 answers from cache, 4 recursions, 0 prefetch, 0 rejected by ip ratelimiting
Mar  3 13:57:41 ddwrt-router daemon.info unbound: [1440:0] info: server stats for thread 1: requestlist max 6 avg 3 exceeded 0 jostled 0
Mar  3 13:57:41 ddwrt-router daemon.info unbound: [1440:0] info: average recursion processing time 0.433470 sec
Mar  3 13:57:41 ddwrt-router daemon.info unbound: [1440:0] info: histogram of recursion processing times
Mar  3 13:57:41 ddwrt-router daemon.info unbound: [1440:0] info: [25%]=0 median[50%]=0 [75%]=0
Mar  3 13:57:41 ddwrt-router daemon.info unbound: [1440:0] info: lower(secs) upper(secs) recursions
Mar  3 13:57:41 ddwrt-router daemon.info unbound: [1440:0] info:    0.262144    0.524288 1
Mar  3 13:57:42 ddwrt-router user.info : unbound : recursive dns resolver daemon successfully started
Mar  3 13:57:42 ddwrt-router daemon.notice unbound: [2123:0] notice: init module 0: validator
Mar  3 13:57:42 ddwrt-router daemon.notice unbound: [2123:0] notice: init module 1: iterator

これで、ルータの再起動後も問題なくUnboundによる宅内フルリゾルバが利用できるようになりました。

まとめ

チェックオンで宅内フルリゾルバがすぐ使えるようになると思ったら、思いがけずはまってしまいました。

そもそも、DD-WRTが動くルータはRTCを搭載していないようなデバイスが多いのに、デフォルトDNSSEC有効にする必要があるのか?という気がすごくするのですが、私だけでしょうか…?

コメント

タイトルとURLをコピーしました