メモ的ななにか

@Maleic1618

RFC 5155: DNS Security (DNSSEC) Hashed Authenticated Denial of Existence (Part 1)

こんにちは、まれいんです。

この記事は ひとりRFCの旅 Advent Calender 7日目の記事です。

qiita.com

今回はDNSSECでネガティブ応答を示すために導入されたNSEC3についてのRFC 5155を読んでいきます。

DNSSECの復習

NSEC3について触れる前に、ベースとなるNSECについて復習します。 詳細が知りたい方は RFC4035 などを参照してください。

DNSSECではネガティブ応答(クエリのリソースレコードやドメインが存在しないことを示す応答)も検証可能にするために、ネガティブ応答に対応するNSECリソースレコードが導入されました。

例えば alpha.example.comecho.example.com というドメイン名が存在していて、かつ辞書式順序でこれらの間に他のドメインが存在しないとします。このとき、間にドメインが存在しないことを示すNSECレコードが用意されます。

例えば以下のようなリソースレコードです。

alpha.example.com.  86400 IN NSEC echo.example.com. A RRSIG NSEC

これらの間に位置するドメイン名(例えば charlie.example.com )を解決するときは、単にNXDOMAINを返すだけでなくこの alpha のNSECリソースレコードも返します。このNSECリソースレコードを検証を以って alphaecho の間にはドメイン名が存在しないこと、すなわち charlie が存在しないことを検証することができます。

また、NSECには指定したドメイン名が所持しているリソースレコードのタイプも埋め込まれています。 そのため、ドメイン名はあるけれどそのタイプのリソースレコードはないよ(つまりNOERROR)、という場合にもNSECリソースレコードを検証することでネガティブ応答を検証することができます。

概要

というわけで導入されたNSECですが、平文で次に存在するドメイン名が含まれているため、順繰りにNSECリソースレコードを見ていくとゾーン内に存在するドメイン名をすべてリストアップすることが出来てしまいます(ゾーン列挙と呼ばれます)

これはあかんということで、ハッシュを利用することでゾーン列挙を避けつつネガティブ応答の検証を可能にしたのが今回のRFCで導入されたNSEC3レコードです。

用語定義

最初にいくつか用語を定義します。

委任

DSリソースレコードがある委任のことを、"Secure"な委任といいます。 逆にDSリソースレコードがない委任のことを、"Insecure"な委任といいます。

Closest (Provable) Encloser

また、RFC4592にて、Closest Encloserを学びました.

クエリ名の "Closest Encloser" とは、存在するドメイン名の中で(ラベル単位で)最長の後方一致するもののことをさします。 存在するものから選ばれるので、closest encloserは(存在すれば)存在するドメイン名となります。

これと似た概念で、検証可能なドメイン名の中で最長の後方一致するもののことを Closest Provable Encloser と呼びます。

closest provable encloser より1ラベル長い名前のことを Next Closer Name と呼びます。

例えば、foo.bar.example.com のclosest provable encloserがexample.comだった場合、next closer nameはbar.example.comになります。(たぶん)

Cover

あるドメイン名AとNSEC3リソースレコードXについて、Xの所有者名と次ハッシュ化所有者名の間にAのハッシュかAのnext closer nameが含まれる場合、XはAをカバーするといいます。

NSEC3 リソースレコード

(非Opt-Outゾーンを考えます)

例えば、example.jp ゾーンにおいて alpha.example.com に対応するNSEC3リソースレコードは、<alphaのhash値>.example.comドメイン名に持つリソースレコードとして作られます。 また、NSECと違い、empty non-terminalsに対しても対応するNSEC3リソースレコードが作られます。

一旦実際に確認してみましょう。 適当にdigすると、ハッシュ化されたドメイン名のNSEC3レコードが確認できます。

$ dig hoge.ad.jp @8.8.8.8 +dnssec

; <<>> DiG 9.16.8-Debian <<>> hoge.ad.jp @8.8.8.8 +dnssec
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 46044
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 8, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 512
;; QUESTION SECTION:
;hoge.ad.jp.                    IN      A

;; AUTHORITY SECTION:
...
MCMJ8BCP73EDE349C25AVISFFPNNF84B.jp. 899 IN NSEC3 1 1 5 E29A0B83BC MCPV242NKRLBJGFMCNTL1QM9PD1V147K TXT RRSIG
...

ここで注意するべきこととして、NSECでは辞書式順序で次のドメイン名を指していましたが、NSEC3ではハッシュ値に対して順序を考えて、次になるドメイン名を記載します。

wire format

ほぼNSECと同様なので、各フィールドの意味だけざっくり拾いましょう。 wire formatは以下です。

                        1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |  ハッシュ     |    フラグ     |           繰り返し            |
   |  アルゴリズム |               |                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |  ソルト長     |                    ソルト                     /
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |  ハッシュ長   |             次ハッシュ化所有者名              /
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   /                    タイプビットマップ                         /
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

フラグのフィールドは以下で、Opt-Outフラグのみが存在する状態です。

    0 1 2 3 4 5 6 7
   +-+-+-+-+-+-+-+-+
   |             |O|
   +-+-+-+-+-+-+-+-+
フィールド名 意味
ハッシュアルゴリズム SHA-1など
フラグ 後で解説
繰り返し ハッシュを繰り返す回数
ソルト長 ソルトの長さ
ソルト ハッシュを取る前に負荷するバイト列
ハッシュ長 「次ハッシュ化所有者名」の長さ
次ハッシュ化所有者名 次のNSEC3 RRのハッシュ化所有者名
タイプビットマップ 「次ハッシュ化所有者名」が持つレコードタイプ一覧

次の式で次ハッシュ化所有者名を計算します。 ソルトと繰り返し回数を指定することで、辞書式攻撃に対抗しやすくなっています。

   NSEC3 RRが指定するハッシュアルゴリズムを使用した x のハッシュをH(x)、
   繰り返し回数を k とする。また、||は結合を意味するものとする。
   ここで、

   k = 0 の場合
      IH(ソルト, x, 0) = H(x || ソルト)

   k > 0 の場合
      IH(ソルト, x, k) = H(IH(ソルト, x, k-1) || ソルト)

   を定義する。

   算出されるハッシュ化所有者名は、

      IH(ソルト, 所有者名, 繰り返し回数)

Opt-Out

"Insecure"な委任がされていることを検証する場合は、タイプビットマップにDSレコードを持たないNSEC3を検証できればOKでした。 しかし、これにはすべての委任に対してNSEC3を作らねばならないため、"Insecure"な委任については用意しなくてよい、という仕組みがOpt-Outです。 (cf. https://dnssec.jp/wp-content/uploads/2010/08/RFC5155.pdf)

NSEC3にOpt-Outフラグが1の場合は、それがカバーするドメイン名に"Insecure"な委任を含んでよいことになりました。("必ず含む"とは言っていないことに注意)

以下では、Opt-Outフラグが1のNSEC3リソースレコードのことをOpt-Out NSEC3リソースレコード、Opt-Out NSEC3リソースレコードを含むゾーンのことをOpt-Outゾーンと呼ぶことにします。

いかに肝となるNSEC3のルールを引用します。

   ・ ゾーン内に権威を持つRRsetを保持する所有者名は、対応するNSEC3 RRを
      持たなければならない(MUST)。未署名委任に対応する所有者名は、
      対応するNSEC3 RRを保持してもよい(MAY)。ただし、対応するNSEC3 RRが
      存在しない場合は、委任の次近接名をカバーするOpt-Out NSEC3 RRが
      存在しなければならない(MUST)。他の権威を持たないRRはNSEC3 RRには
      表記されない。

次回予告

長編となってしまうため今回のRFC5155についてはPartを分割し、権威サーバ側はどのようにNSEC3を用意すればよいか、検証側はどのようにNSEC3を使って検証すればよいかについて触れます。

1日1RFCの予定でしたが、3日くらいかけてこの記事の内容だけしか読み解けなかったので弱音を吐かせてください! よろしくお願いします<( ;;)>