DNSのシリアル番号、数字が小さくても新しい版になる理由

ミント色と桃色の半円が継ぎ目で接する円形の軌道と、その向かい合う位置に置かれた二つの薄紫の球。

DNSの設定を複数のサーバーでそろえるとき、「どちらが新しい版か」を表すのがSOAレコードのシリアル番号です。ところが、数字として小さい番号が新しい版になる場合があります。番号を入れる場所の大きさが有限で、上限の次に先頭へ戻るためです。ここでは、この折り返しを扱うSerial Number Arithmetic(シリアル番号演算)を、小さな数の例で確かめます。

簡単にまとめると?

  • DNSのSOAシリアル番号は32ビット。通常の整数の大小だけでは、折り返し後の新旧を判定できません。
  • 前向きの差が番号空間の半分未満なら新しい側、半分ちょうどなら大小関係は未定義です。
  • 小さな更新を繰り返しても、長く取り残された版との関係には注意が必要です。番号の比較と、各サーバーへの反映確認を分けます。

SOAの番号は、設定の版を比べるためにある

SOA(Start of Authority)は、DNSの管理範囲であるゾーンについて、版番号や更新確認に関わる値を持つレコードです。RFC 1035のSERIAL欄は符号なし32ビットの版番号で、ゾーン転送でもその値を保ちます。EXPIRE欄は、ゾーンの情報を権威ある情報として扱い続けられる期限に関わります。版番号と時間の値は、同じSOAに入っていても役割が異なります。

番号が一致したことは「番号が同じ」という観測です。それだけで、設定内容の誤りがないことや、すべての利用者が新しい応答を受けたことまでは証明できません。この記事が扱うのは、二つの版番号を比較する規則です。

16個の番号で、折り返しを見てみる

実際のDNSでは0から4,294,967,295までの値を使います。まず説明用に4ビット、つまり0から15までの16個へ縮めます。これはDNSの設定値を4ビットにする提案ではありません。

旧版を14とし、3回分進めると、15、0、1となります。新しい番号は1ですが、普通の整数比較では1は14より小さくなります。この食い違いを避けるため、比較では「旧版から候補へ、折り返しを含めて前向きにどれだけ離れているか」を求めます。

候補をb、旧版をa、番号空間の大きさをMとすると、差dは(b − a) mod Mです。ここでmodは、0以上M未満になる余りを取る操作です。負数の余りの扱いが言語によって異なるため、式を実装するときはこの範囲へそろえる必要があります。

説明用4ビット空間で、旧14から候補1への前向き差は3で新しい。旧14から候補6は差8で大小未定義。旧14から候補13は差15で古い。各差は16で折り返して計算。
説明用の4ビット空間で、旧版14と三つの候補を比較した独自計算。実際のDNSは32ビットであり、この図はDNSサーバーの実測結果ではありません。

16個の番号では半分が8です。差が0なら同じ、1から7なら候補が新しい、9から15なら候補が古いと判定します。差8だけは、どちらを大きいとするかが規則で決まりません。RFC 1982の比較規則を、この小さな空間へ当てはめたものです。

具体的には、旧14・候補1ならd=3で新しい側です。旧14・候補13ならd=15で古い側です。旧14・候補6ならd=8となり、大小未定義です。「同じ」でも「必ずエラーを返す」でもありません。特定の大小結果を前提に使わない境界です。

一回ずつ正しく進めても、古い版から見ると逆転する

次に、4ビットの番号を1→7→13と進めます。どちらの一歩も増分は6なので、半周の8未満です。7は1より新しく、13は7より新しいと判定できます。

ところが、最初の1だけを覚えている側が13を見ると、前向きの差は12です。半周を超えるため、比較上は13が古い側になります。途中の更新を見た側と見逃した側で、見えている関係が異なるのです。各一歩の合法性だけでは、長く残った版から最後の版を比較できる保証になりません。

この例はもう一つの注意も示します。1より7が新しく、7より13が新しくても、1と13の関係まで普通の数直線の順序としてつなげられません。シリアル番号を、任意に長い履歴を一列に並べるための単純なソートキーとして扱うのは適しません。

32ビットで境界を確かめる

DNSではM=4,294,967,296、半周は2,147,483,648です。たとえば旧4,294,967,294から候補1への差は3となり、候補が新しいと判定できます。これは「桁が小さくなったから巻き戻った」とは限らない具体例です。

一方、旧100と候補2,147,483,748の差は半周ちょうどです。大小は未定義になります。候補2,147,483,747なら差は半周より1小さく、新しい側です。たった1の違いでも境界の意味が変わります。

RFC 1982は、一度に加えてよい増分を0から2,147,483,647までと定め、SOAのEXPIREに相当する期間内の累積増分にも注意を求めています。大きく番号を飛ばして修正するときは、手元の一台との比較だけでは十分でない場合があります。

反映を調べるときに、何を残すか

運用記録には、新しい値だけでなく、各サーバーで観測した旧値・候補値・観測時刻を組にして残すと比較できます。同じ候補でも、旧値が違えば差が変わるためです。前の例なら、旧値7のサーバーと旧値1のサーバーを一つにまとめてしまうと、結果の違いを見落とします。

比較コードを確認するなら、通常の増加だけでなく、折り返し、同値、半周ちょうど、その前後を含めると境界を点検できます。この記事では説明用4ビットの全256組を規格の不等式と照合し、32ビットの上記例も計算しました。ただし、これは数式と例の検証です。利用中のDNSソフトウェアや実際のゾーン転送を試験したものではありません。

シリアル番号から分かるのは、決められた範囲内での版の前後関係です。番号の比較が成立すること、必要なサーバーが更新を受け取ったこと、公開したDNSデータが意図どおりであることを、それぞれ確かめると状況を取り違えにくくなります。

出典