Raspberry Pi 3 で動作中の CentOS 7 で bind が名前解決しなくなる問題を解決

スポンサーリンク

 昨日ちょろっと Raspberry Pi 3 上の CentOS 7 に SSH して DNS ちゃんと動いてるかなーってログ見たらエラーだらけ。
 dig @localhost example.com. in any なんてしても何一つ応答が無い。つまり引けていないという事に。これはマズい。
 named.log に表示される主たるエラーはこれ。

16-Jun-2018 01:30:12.810 dnssec:   validating @0x7030dd78: . DNSKEY: unable to find a DNSKEY which verifies the DNSKEY RRset and also matches a trusted key for '.'
16-Jun-2018 01:30:12.810 dnssec:   validating @0x7030dd78: . DNSKEY: please check the 'trusted-keys' for '.' in named.conf.

 要はトラストアンカーを確認しろという事で。
 しかし trusted-keys に示される署名を最新に切り替えたところでどうというわけもなくエラーは出る。
 次にピンと来たのは時間
 named.log を見ているとちらほらと 01-Jan-1970 09:00:09.990 等という時間で記録されているところが目に付く。この時間で示される箇所は named の起動時。
 つまり Raspberry Pi 3 を再起動したとき、時刻同期が行われる前に named が起動した場合に 1970 年に動作していると認識されてトラストアンカーの署名も有効期限が無効とされてしまうことに起因すると判断。
 毎回再起動後に手動で named を再起動させれば問題なく名前解決をしてくれるがそれは流石に面倒過ぎるし実用的ではない。

 解決方法を模索する為に色々考えていたら「時刻同期後に named を起動すれば良い」という単純な所に行き着いた。
 /lib/systemd/system 以下の unit ファイルを眺めていると NTP として使用している chronyd の unit には chrony-wait.service というサービスが存在した。
 このサービスは chronyd 起動後に時刻同期をするまで待ってくれる代物だと受け取れた。
 期待通りの動作をしてくれるかわからないので取り敢えず設定をしてみる。

systemctl enable chrony-wait.service
systemctl start chrony-wait.service
systemctl status chrony-wait.service
● chrony-wait.service - Wait for chrony to synchronize system clock
   Loaded: loaded (/usr/lib/systemd/system/chrony-wait.service; enabled; vendor preset: disabled)
   Active: active (exited) since 土 2018-06-16 01:30:55 JST; 18min ago
     Docs: man:chronyc(1)
  Process: 292 ExecStart=/usr/bin/chronyc -h 127.0.0.1,::1 waitsync 600 0.1 0.0 1 (code=exited, status=0/SUCCESS)
 Main PID: 292 (code=exited, status=0/SUCCESS)
   CGroup: /system.slice/chrony-wait.service

 1月 01 09:00:08 rpi.bp7.org systemd[1]: Starting Wait for chrony to synchronize system clock...
 6月 16 01:30:55 rpi.bp7.org systemd[1]: Started Wait for chrony to synchronize system clock.

 systemd 経由で自動起動するように設定した後、手動で起動させてステータスを見ることで動作しているか確認。
 その後、/lib/systemd/system/named-chroot.service を編集した。
 追記する物は 11 行目に入れた “After=chrony-wait.service” だけ。

# Don't forget to add "$AddUnixListenSocket /var/named/chroot/dev/log"
# line to your /etc/rsyslog.conf file. Otherwise your logging becomes
# broken when rsyslogd daemon is restarted (due update, for example).

[Unit]
Description=Berkeley Internet Name Domain (DNS)
Wants=nss-lookup.target
Requires=named-chroot-setup.service
Before=nss-lookup.target
After=NetworkManager-wait-online.service
After=chrony-wait.service
After=named-chroot-setup.service

[Service]
Type=forking
Environment=NAMEDCONF=/etc/named.conf
EnvironmentFile=-/etc/sysconfig/named
Environment=KRB5_KTNAME=/etc/named.keytab
PIDFile=/var/named/chroot/run/named/named.pid

ExecStartPre=/bin/bash -c 'if [ ! "$DISABLE_ZONE_CHECKING" == "yes" ]; then /usr/sbin/named-checkconf -t /var/named/chroot -z "$NAMEDCONF"; else echo "Checking of zone files is disabled"; fi'
ExecStart=/usr/sbin/named -u named -c ${NAMEDCONF} -t /var/named/chroot $OPTIONS

ExecReload=/bin/sh -c '/usr/sbin/rndc reload > /dev/null 2>&1 || /bin/kill -HUP $MAINPID'

ExecStop=/bin/sh -c '/usr/sbin/rndc stop > /dev/null 2>&1 || /bin/kill -TERM $MAINPID'

PrivateTmp=false

[Install]
WantedBy=multi-user.target

 最後に OS を再起動させて期待通り時刻同期後に named が起動することを確認する。
 /var/log/message をケツから覗いて確認するとこうなった。

Jan  1 09:00:11 rpi systemd: postfix.service failed.
Jun 16 01:30:55 rpi chronyd[225]: Selected source ***.***.***.***
Jun 16 01:30:55 rpi chronyd[225]: System clock wrong by 1529080239.216336 seconds, adjustment started
Jun 16 01:30:55 rpi systemd: Time has been changed
Jun 16 01:30:55 rpi chronyd[225]: System clock was stepped by 1529080239.216336 seconds
Jun 16 01:30:55 rpi rsyslogd: imjournal: journal reloaded... [v8.24.0 try http://www.rsyslog.com/e/0 ]
Jun 16 01:30:55 rpi systemd: Started Wait for chrony to synchronize system clock.
Jun 16 01:30:55 rpi systemd: Reached target System Time Synchronized.
Jun 16 01:30:55 rpi systemd: Starting System Time Synchronized.
Jun 16 01:30:55 rpi systemd: Started Command Scheduler.
Jun 16 01:30:55 rpi systemd: Starting Command Scheduler...
Jun 16 01:30:55 rpi systemd: Starting Berkeley Internet Name Domain (DNS)...

 最初の行では時刻同期していないので postfix の起動失敗ログが出ている。これは使ってないので問題は無い。
 次の行から chronyd が同期先を選んで同期、最終行で named が正しい時間に起動を開始している。
 よって先に書いたトラストアンカーの署名に関しても問題なく検証されてエラー無く名前解決も出来るようになった。

 そもそもなんでこんな事が―― といえば Raspberry Pi 3 は RTC を持たないのでリセットすると時間を保持することが出来ずに UNIX 時間の頭からとなってしまうから。
 通常のサーバー機では完全に不要な作業だろうけど Raspberry Pi 3 上の Linux で DNS を動作させるなら必須となってくる作業かなと思う。

スポンサーリンク