BIND9 ゾーンファイルの編集の罠
BIND9にて、ゾーン情報の編集を以下の流れでやった場合に、変更後の情報が反映されない事象が発生しました。
- 現在のゾーンファイル(zone.example.com)を別名にコピー(zone.example.com_copy)して、内容を編集(シリアル値はもちろんあげておく)
- 1.の作業から少ししてから、現在のゾーンファイル(zone.example.com)を編集して、BINDに再読み込みさせる
- 2.の作業の後に、現在のゾーンファイル(zone.example.com)を別名(zone.example.com_back)にして、zone.example.com_copyをzone.example.comにして、BINDに再読み込みさせる
この場合、2. においては、意図したとおりゾーンファイルの情報が再読み込みされるにも関わらず、3. の場合には、 再読み込みがされません(もちろんシリアル値は、大きくなっている)。
コマンドで上記を追うと、以下のようになる。
# cat zone.example.com ;$ORIGIN . ;$TTL 600 ; 10 minutes $TTL 60 ; 1 minutes @ IN SOA ns.example.com. abuse.example.com. ( 2019090900 ; serial 3600 ; refresh (1 hour) 900 ; retry (15 minutes) 604800 ; expire (1 week) 86400 ; minimum (1 day) ) NS ns.example.com. ns A 172.16.3.1 test1 A 172.16.3.1 # dig +norec +short @172.16.3.1 test1.example.com 172.16.3.1 # dig +norec +short @172.16.3.1 test2.example.com # 登録がないのでレスポンスなし # dig +norec +short @172.16.3.1 test3.example.com # 登録がないのでレスポンスなし # cp -iva zone.example.com zone.example.com_copy 'zone.example.com' -> 'zone.example.com_copy' # vi zone.example.com_copy # cat zone.example.com_copy ;$ORIGIN . ;$TTL 600 ; 10 minutes $TTL 60 ; 1 minutes @ IN SOA ns.example.com. abuse.example.com. ( 2019090910 ; serial ; <-- 大きめに変更 3600 ; refresh (1 hour) 900 ; retry (15 minutes) 604800 ; expire (1 week) 86400 ; minimum (1 day) ) NS ns.example.com. ns A 172.16.3.1 test1 A 172.16.3.1 test3 A 172.16.3.1 ; <-- 追加した # ls -la total 16 drwxr-xr-x 2 root root 4096 Sep 9 18:01 . drwxrwxr-x 3 root bind 4096 Sep 9 17:54 .. -rw-r--r-- 1 bind bind 334 Sep 9 17:56 zone.example.com -rw-r--r-- 1 bind bind 355 Sep 9 18:01 zone.example.com_copy # vi zone.example.com # cat zone.example.com ;$ORIGIN . ;$TTL 600 ; 10 minutes $TTL 60 ; 1 minutes @ IN SOA ns.example.com. abuse.example.com. ( 2019090901 ; serial 3600 ; refresh (1 hour) 900 ; retry (15 minutes) 604800 ; expire (1 week) 86400 ; minimum (1 day) ) NS ns.example.com. ns A 172.16.3.1 test1 A 172.16.3.1 test2 A 172.16.3.1 ; <-- 追加した # vi zone.example.com # ls -la total 16 drwxr-xr-x 2 root root 4096 Sep 9 18:02 . drwxrwxr-x 3 root bind 4096 Sep 9 17:54 .. -rw-r--r-- 1 bind bind 355 Sep 9 18:02 zone.example.com # <-- こっちのタイムスタンプの方が新しい -rw-r--r-- 1 bind bind 355 Sep 9 18:01 zone.example.com_copy # rndc reload example.com # 【リロード(1)】 zone reload queued # dig +norec +short @172.16.3.1 test1.example.com 172.16.3.1 # dig +norec +short @172.16.3.1 test2.example.com # <-- 追加したので出るようになった(意図通り) 172.16.3.1 # dig +norec +short @172.16.3.1 test3.example.com # mv -iv zone.example.com zone.example.com_back 'zone.example.com' -> 'zone.example.com_back' # mv -iv zone.example.com_copy zone.example.com 'zone.example.com_copy' -> 'zone.example.com' # ls -la total 16 drwxr-xr-x 2 root root 4096 Sep 9 18:04 . drwxrwxr-x 3 root bind 4096 Sep 9 17:54 .. -rw-r--r-- 1 bind bind 355 Sep 9 18:01 zone.example.com # <-- mvで入れ替えたのでタイムスタンプが古いママ -rw-r--r-- 1 bind bind 355 Sep 9 18:02 zone.example.com_back # rndc reload example.com # 【リロード(2)】 zone reload up-to-date # dig +norec +short @172.16.3.1 test1.example.com 172.16.3.1 # dig +norec +short @172.16.3.1 test2.example.com # <-- でないはずなのに出る 172.16.3.1 # dig +norec +short @172.16.3.1 test3.example.com # <-- でるはずなのに出ない # touch zone.example.com # <-- タイムスタンプを新しくする # ls -la total 16 drwxr-xr-x 2 root root 4096 Sep 9 18:04 . drwxrwxr-x 3 root bind 4096 Sep 9 17:54 .. -rw-r--r-- 1 bind bind 355 Sep 9 18:05 zone.example.com -rw-r--r-- 1 bind bind 355 Sep 9 18:02 zone.example.com_back # rndc reload example.com # 【リロード(3)】 zone reload queued # dig +norec +short @172.16.3.1 test1.example.com 172.16.3.1 # dig +norec +short @172.16.3.1 test2.example.com # <-- でなくなった(意図通り) # dig +norec +short @172.16.3.1 test3.example.com # <-- でるようになった(意図通り) 172.16.3.1
syslogには、以下のようにログが出力される。
【リロード(2)】のときには、「zone example.com/IN: loaded serial 2019090901」のように読み込んだファイルのシリアル値のログが出ていない。
Sep 9 18:03:50 localhost named[25597]: received control channel command 'reload example.com' Sep 9 18:03:50 localhost named[25597]: zone example.com/IN: loaded serial 2019090901 Sep 9 18:04:52 localhost named[25597]: received control channel command 'reload example.com' Sep 9 18:05:13 localhost named[25597]: received control channel command 'reload example.com' Sep 9 18:05:13 localhost named[25597]: zone example.com/IN: loaded serial 2019090910
これは、ゾーンファイルの再読込について、ゾーンファイルの中身(シリアル値)が確認される前に、ゾーンファイルのタイムスタンプをBINDが確認しているためで、現在読み込まれているファイルのタイムスタンプよりも新しくなっていないと、再読込されない仕様なようです。
上のページの3段落目に、
the decision on whether or not the zone has changed is the serial number that is maintained in the zone's SOA record (although when a master reloads, it does also check the timestamp on the zone data file first, before checking the zone's SOA).
と書かれています。
普通に更新したら、ファイルのタイムスタンプは新しくなるだろうけど、上のように事前に用意しておいたファイルと置き換えるときには注意が必要なようです。