BlueOnyxでゾーンファイルのシリアル値が11桁になるバグ

  • 投稿日:
  • by
  • カテゴリ:    

BlueOnyxではWebの管理画面からDNSの設定を手軽に変更できますが、注意点があります。

タイトルの通りではありますが、ゾーンファイルのシリアル値が11桁になることがあります。

シリアル値は、yyyymmddにシーケンス番号2桁を加えた形となっていますが、 正規表現によるチェックで境界条件がよろしくありません。

/usr/sausalito/handlers/base/dns/dns_generate.pl

L.829付近のgenerate_soa_record関数でシリアル値の生成を行っています。

########################################
# generate_soa_record
########################################
sub generate_soa_record
{
  my $self = shift;

  my $fname = $self->db_file_name();
  my $db_file = "${named_dir}/${fname}";

  my(@Time) = localtime(time);
  $Time[5] += 1900;
  $Time[4]++;
  for (my $i=0;$i<=5;$i++) {
    $Time[$i] = ($Time[$i] < 10) ? "0$Time[$i]" : "$Time[$i]";
  }
  my $today = "$Time[5]$Time[4]$Time[3]";

  my $serial_number = $today . "01";

  if (-e $db_file) {
    open (IN, "< $db_file");
    while () {
      if (/\s*([0-9]{8})([0-9]{2}) ; serial number/) {
        my $date = $1;
        my $suffix = $2;
        if ($date eq $today) {
          $suffix++;
          $serial_number = $today . $suffix;
        }
      }
    }
    close(IN);
  }

以下の条件で既存のゾーンファイルのシリアル値をチェックしていますが、"yyyymmdd99"でもマッチしてしまいます。 日付が同一だった場合に、$suffix++;によって11桁(100)となってしまいます。

if (/\s*([0-9]{8})([0-9]{2}) ; serial number/) {

11桁で不味い理由は、シリアル値が32bit正数で取りうる値が、0~4,294,967,295までのため。

※シリアル値は、CODB(Cobalt Object DataBase)で管理されず、ゾーンファイルの値を取得しています。CODBを覗いてみるとシリアル値が管理されていないことが確認できます。

# /usr/sausalito/bin/cceclient
100 CSCP/0.99
200 READY

classes
110 CLASS pam_abl_settings
110 CLASS FtpSite
110 CLASS Vsite
110 CLASS VsiteServices
110 CLASS WebApplications
110 CLASS EmailAlias
110 CLASS CapabilityGroup
110 CLASS VirtualHost
110 CLASS SOL_Console
110 CLASS SWUpdateServer
110 CLASS ProtectedEmailAlias
110 CLASS DnsSOA
110 CLASS Network
110 CLASS PHP
110 CLASS Package
110 CLASS JavaWar
110 CLASS MySQL
110 CLASS UserServices
110 CLASS Capabilities
110 CLASS User
110 CLASS Disk
110 CLASS DnsSlaveZone
110 CLASS dnsbl
110 CLASS MailList
110 CLASS Schedule
110 CLASS Subdomains
110 CLASS ServiceQuota
110 CLASS IPPoolingRange
110 CLASS ActiveMonitor
110 CLASS Shop
110 CLASS WebApplicationsList
110 CLASS DnsRecord
110 CLASS Workgroup
110 CLASS UserExtraServices
110 CLASS System
110 CLASS mx2
110 CLASS Route
201 OK

find DnsSOA
104 OBJECT 49
201 OK

get 49
102 DATA NAMESPACE = ""
102 DATA primary_dns = ""
102 DATA secondary_dns = ""
102 DATA CLASSVER = "1.0"
102 DATA CLASS = "DnsSOA"
102 DATA netmask = ""
102 DATA domainname = "example.co.jp"
102 DATA ipaddr = ""
102 DATA refresh = "10800"
102 DATA OID = "49"
102 DATA domain_admin = ""
102 DATA retry = "3600"
102 DATA expire = "604800"
102 DATA ttl = "86400"
201 OK

バグの確認

11桁になることを確認してみます。現在のシリアル値を確認します。

[root@localhost named]# cd /var/named/chroot/var/named
[root@localhost named]# find . -type f -not -name '*~' -print | xargs grep serial
./db.example.co.jp: 2019120706 ; serial number
./db.example.com:   2019120705 ; serial number

example.co.jpのシリアル値を"2019120799"に変更します。

[root@localhost named]# sed -i -e 's/2019120706/2019120799/' db.example.co.jp
[root@localhost named]# find . -type f -not -name '*~' -print | xargs grep serial
./db.example.co.jp: 2019120799 ; serial number
./db.example.com:   2019120705 ; serial number
[root@localhost named]#

管理画面から「保存」してみます。以下の画面で「保存」ボタンを押下します。

[root@localhost named]# find . -type f -not -name '*~' -print | xargs grep serial
./db.example.co.jp: 20191207100 ; serial number
./db.example.com:   2019120706 ; serial number

11桁になっていますね。因みに、この状態からもう一度「保存」ボタンを押下すると、$suffixは"01"に戻ります。

1日に100回もリソースレコードを修正するケースはあまりないと思いますが、注意点があります。

BlueOnyxの管理画面で、「ネットワークサービス」→「DNS」→「プライマリサービスを設定」で表示される画面の「保存」ボタンを押下すると、全ゾーンファイルのシリアル値が更新されてしまいます(※RRレコードをいじったかどうかは関係ありません)。

移行作業等で、cmuExportしたサイトをcmuImportした場合も同様に1サイトをインポートする毎に全ゾーンファイルのシリアル値が更新されるため、100を超えるケースが出て来る可能性がありますのでご注意を!