2012年9月2日日曜日

DNSSEC Look-aside Verification を使うべきでない3つの理由

DNSSEC は本来ルートゾーンから順番に証明していき、最後にホストのレコードを確認するという仕組みになっています。ところが、大人の事情で上位ゾーンに鍵を登録できない人のために、DNSSEC Look-aside Verification (DLV, RFC5074) という仕組みがあります。

DLV は、以下のような仕組みで動きます。

  1. example.net をルートゾーンからの連鎖で証明しようとする
  2. どこかで連鎖が止まっている(上位ゾーンに登録されていない)ため、確認できない
  3. example.net.dlv.isc.org をに DLV レコード(DS レコードとほぼ同等)が登録されていないか確認する
  4. 得られた DLV レコードを使って example.net の証明をする

この dlv.isc.org を DLV に使って良いというのは別途設定し、 trust anchor をリゾルバに登録しておきます。

これだけ見ると、一見便利そうなのですが、私は使うべきではないと思います。3つほど理由をあげます。

DLV を有効にすると遅くなる

本来の認証の連鎖が途切れた時に DLV が引かれますので、単純に2倍以上遅くなります。さらに、日本からだと dlv.isc.org の NS が遠くにあるので、かなり待たされます。これは単純にレスポンスの悪化につながります。

グラフは DNSSEC on, DNSSEC on + DLV有効, DNSSEC オフでそれぞれ名前を引いてみた場合の、レスポンスタイムになります(5回平均)。 jprs.jp は DNSSEC の鍵が正しく登録されているドメイン、yuryu.jp はされていないドメインになります。 計測は unbound 1.4.18 を用い、毎回の計測の前にリスタートしてキャッシュをクリアしています。また、実際のクエリタイムに近づけるために、 .jp 及び dlv.isc.org の SOA をクエリして、上位ゾーン情報はキャッシュ済みの状態です。

jprs.jp は上位ゾーンからの連鎖で正しく証明ができるので、 DLV のオンオフにかかわらずクエリタイムは一定です。ところが、 yuryu.jp のように証明できないドメインだと、 DLV のクエリが追加で走るのでとても遅くなります。 DNSSEC の on/off よりも重大なパフォーマンスの低下をもたらします。

DNSSEC がきちんと普及すれば問題ないのですが、DLV は「普及過程のためのworkaround」という位置づけです。ほとんどのドメインが署名されていない現状で、このパフォーマンス低下は許容できません。

鍵更新のポリシーが不透明

ルートゾーンの KSK は定期的に更新される、少なくとも5年に1度は更新されることになっています。また、 IANA によって鍵更新ポリシーや記録がきちんとメンテされています。 DLV のキーはこれと同等の基準では運用されていません。一応ポリシーは書かれてあるんですが、そこには「年1回 KSK 更新します」とあります。ところが実際には 2008年から鍵は更新されていません。

ソフトウェアのサポートが不十分

BIND は DLV の trust anchor も含めて自動更新に対応しています。ところが、 unbound の場合はルートゾーンの trust anchor については自動更新に対応しているものの、 DLV trust anchor は自動更新しません。

もし KSK が更新されたとなると、 trust anchor も含めてアップデートしなければなりませんが、これが人力になってしまいます。放置すると証明できないゾーンが生まれることになります。

そして、別の記事にも書きましたが、リゾルバによって挙動が異なる場合があります。利用者も少ないので、枯れているとは言いがたい状況です。

まとめ

以上3つの理由により、少なくとも現状は DLV を使うのは望ましくないと思います。 ルートゾーンが署名され、多くの ccTLD も署名されつつありますから、無理に DLV を用いて DNSSEC を導入するのではなく、上位ゾーンの対応を待つべきでしょう。

BIND9 で DLV が期待した動きをしない

大人の事情で最近 DNSSEC にはまってます。 unbound も BIND も、新し目のバージョンは標準対応しているし、標準で有効になっているのですが、どうも BIND で DLV を使おうとすると、うまく動きませんでした。

環境は以下のとおりです。

  • Ubuntu 12.04 LTS, kernel 3.2.0-29 amd64
  • Unbound 1.4.18
  • BIND 9.9.1-P2
  • OpenSSL 1.0.1

DNSSEC には、自分の上位ゾーンが署名に対応していない場合に備えて、 DLV(DNS Look-aside Verification )という仕組みがあります。おおまかに言うと、本来はルートゾーンから順繰りにたどっていってドメインの認証をするのですが、その代わりに ドメイン名.dlv.isc.org を問い合わせて、 DS レコードの代わりに DLV レコードを引っ張ってきてドメインの認証をします。これが BIND9 でうまく動きません。

テストには DNS-OARC から提供されているテストレコード を使用しました。

まず unbound 1.4.18 での想定通りの動きです。

~/bind/9.9.1 $ bin/dig -p 1418 @localhost +dnssec a.nsec.dlvtest.dns-oarc.net txt

; <<>> DiG 9.9.1-P2 <<>> -p 1418 @localhost +dnssec a.nsec.dlvtest.dns-oarc.net txt
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 58334
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 4096
;; QUESTION SECTION:
;a.nsec.dlvtest.dns-oarc.net.   IN      TXT

;; ANSWER SECTION:
a.nsec.dlvtest.dns-oarc.net. 917 IN     TXT     "A is for AXFR"
a.nsec.dlvtest.dns-oarc.net. 917 IN     RRSIG   TXT 5 5 3600 20310611060557 20110616060557 54345 nsec.dlvtest.dns-oarc.net. c4CXn8ejvaiexLq5FuQv6bFrfRlUGF//2jew7rGqICUZAj0lEdLkxu6Y H47SrIjYIb0xwzO2QMnVcLKAvVfuozQ8bq/mgn0x7RHQ32Bh0ZS55scw Wxji8iCHxcr5rzxtkMcAZzjx28A/ir+jKizfF8RCEv3MtPqd7+Y71YCk 0Jw=

;; Query time: 0 msec
;; SERVER: 127.0.0.1#1418(127.0.0.1)
;; WHEN: Sun Sep  2 00:39:06 2012
;; MSG SIZE  rcvd: 267

きちんと引けてますね。 flags に "ad" が入っていれば DNSSEC により認証ができたという意味です。

さて次は BIND9 です。

~/bind/9.9.1 $ bin/dig -p 9912 @localhost +dnssec a.nsec.dlvtest.dns-oarc.net txt

; <<>> DiG 9.9.1-P2 <<>> -p 9912 @localhost +dnssec a.nsec.dlvtest.dns-oarc.net txt
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 21002
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 4096
;; QUESTION SECTION:
;a.nsec.dlvtest.dns-oarc.net.   IN      TXT

;; Query time: 1690 msec
;; SERVER: 127.0.0.1#9912(127.0.0.1)
;; WHEN: Sun Sep  2 00:38:28 2012
;; MSG SIZE  rcvd: 56

待たされた挙句 SERVFAIL になってしまいました。ところが、 BIND を再起動した上で次の手順を踏むと、引けるようになります。

  1. 一つ上のゾーンについて ANY で DNSKEY を取ってくる
  2. 目的のゾーンについてクエリを投げる
~/bind/9.9.1 $ bin/dig -p 9912 @localhost +dnssec nsec.dlvtest.dns-oarc.net any

; <<>> DiG 9.9.1-P2 <<>> -p 9912 @localhost +dnssec nsec.dlvtest.dns-oarc.net any
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 45581
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 5, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 4096
;; QUESTION SECTION:
;nsec.dlvtest.dns-oarc.net.     IN      ANY

;; ANSWER SECTION:
nsec.dlvtest.dns-oarc.net. 3600 IN      RRSIG   DNSKEY 5 4 3600 20310611060557 20110616060557 23716 nsec.dlvtest.dns-oarc.net. EIBG75iE6v53oOOI1PfWvrvMi0qHYigxrtJMTdMdFUHzZrh71+hZSM88 ILw6UUvotyb9YUH1opjB4iA9Ks8ZBqaSn+AwzbP6pNfMRFiNVlYoLBLq y6cERjpb/6jUr/dxGq/57VThi8BYjiHF1aYv3vgSLhCvfvI2tvnfgxlN YeL286GDojf9bSaQrrHOcWdqivTibiBarxNrAfxHGE3MIpX1eZUGsXL4 aHrMv7n7juy86mfm+lZg7y4JfT32IADygbdTWQQYF8P7TYzPZof38D6s cYnvYCx+m770Uj9Z3z7eTHkk5AgvTDcorNVp/xPFPqGaJ9iwReMoeE9N wngNtA==
nsec.dlvtest.dns-oarc.net. 3600 IN      RRSIG   DNSKEY 5 4 3600 20310611060557 20110616060557 54345 nsec.dlvtest.dns-oarc.net. UiNDgsQdHdb2Tni4d6ebGajNwmxTFk+6gvil9M4/stimqOnL2RQqX6Kb IASX+8z4AzYVQFsb7OCyGugmsBc5ukjTR4at2j3sp6Xjk4r7J5DMAADY ZHTgBua2AOySy/DdVTfTdRK4YbQcHLggw3Nr8r64daD14SFUAL2nGOSk cNM=
nsec.dlvtest.dns-oarc.net. 3600 IN      DNSKEY  257 3 5 AwEAAejxNtUB1RBO7DZP1NtC2V46LWt5r2XM5ykywFYmeG6LCmn6oafG 27djNKFyCHWAmNmZXaQXg60YAGT8XQdMrmvidPCQqrB7w2ZO0w/rEqVp 74KT46yuTKGBOUFJ4nWLw77mvxG4v8HEhvZUyYspLvBSt/qi72S66SP2 njyymaQbZAT0ZP4NsjO6L8UugDwGJuRdd1qXyOLf9blogviFjdFe7Y8a TV071VCSj7/iTg0sqPlZvy5kZB1Sz+yE/xrvqDA7WIMDpr5nahWPbAzm NigLZFy1+PKF4U4ZTp3t9+kPqWpSBE0NpfaGY79b96JRMRHtGM/+TqWj 79jRZyUE1oU=
nsec.dlvtest.dns-oarc.net. 3600 IN      DNSKEY  256 3 5 AwEAAfGatB0iI+BHO7JStuOFATy2iRyVDnmdCsdDTgtINKtcIqKWbw7w xjQ3dXhUSrjVVfEHJIScxiyjBJ0u1mG4FhY0zGusenn5R6RuhTAjZ/Ow wvp+1X1orWdwUVncYS3a+sGfyr4XBbFQSSB0HLSZxzskPbNQ1NR8fX2L iy8V89Zv
nsec.dlvtest.dns-oarc.net. 3600 IN      DNSKEY  256 3 5 AwEAAamEbJrkD6whOxQH7y+JhH5AH5kwjXfG43p9SJ/j0d+58tcK2cuQ 4rpXGD0KybG8rte7F0ja0Dlv9PFhL2UqKrdtk43ZLwZjAnotcTODqDog D8EHEOTwt2LMy9FGTf40IgoUQfG3PxcJsAkNOswqw41vu5Te4mzzDhrh AQWRldL5

;; Query time: 1578 msec
;; SERVER: 127.0.0.1#9912(127.0.0.1)
;; WHEN: Sun Sep  2 00:37:11 2012
;; MSG SIZE  rcvd: 1124

~/bind/9.9.1 $ bin/dig -p 9912 @localhost +dnssec a.nsec.dlvtest.dns-oarc.net txt

; <<>> DiG 9.9.1-P2 <<>> -p 9912 @localhost +dnssec a.nsec.dlvtest.dns-oarc.net txt
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 25080
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 3, ADDITIONAL: 2

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 4096
;; QUESTION SECTION:
;a.nsec.dlvtest.dns-oarc.net.   IN      TXT

;; ANSWER SECTION:
a.nsec.dlvtest.dns-oarc.net. 3600 IN    TXT     "A is for AXFR"
a.nsec.dlvtest.dns-oarc.net. 3600 IN    RRSIG   TXT 5 5 3600 20310611060557 20110616060557 54345 nsec.dlvtest.dns-oarc.net. c4CXn8ejvaiexLq5FuQv6bFrfRlUGF//2jew7rGqICUZAj0lEdLkxu6Y H47SrIjYIb0xwzO2QMnVcLKAvVfuozQ8bq/mgn0x7RHQ32Bh0ZS55scw Wxji8iCHxcr5rzxtkMcAZzjx28A/ir+jKizfF8RCEv3MtPqd7+Y71YCk 0Jw=

;; AUTHORITY SECTION:
nsec.dlvtest.dns-oarc.net. 3600 IN      NS      ns.dns-oarc.net.
nsec.dlvtest.dns-oarc.net. 3600 IN      NS      sns-pb.isc.org.
nsec.dlvtest.dns-oarc.net. 3600 IN      RRSIG   NS 5 4 3600 20310611060557 20110616060557 54345 nsec.dlvtest.dns-oarc.net. E0FInFhHCmZ/C6jh8+QZ0HP5V4GYXBLvEbSiCYTVJgsvRXIbBdzAG4MN jUgMFnrSjyCKOGSelrD4whnbOExD6MdtY0Vwq6xMt1XIpjRc6JoG8ja6 DL5qwlqb5NtRQCV2Z2FDT6QuXtyr6ODh7amj+YSWCOW5cS25DYmBcsnC 2UU=

;; ADDITIONAL SECTION:
ns.dns-oarc.net.        172791  IN      A       149.20.58.65

;; Query time: 118 msec
;; SERVER: 127.0.0.1#9912(127.0.0.1)
;; WHEN: Sun Sep  2 00:37:18 2012
;; MSG SIZE  rcvd: 513

"ad" も立っていて、正常に認証できていると示されています。ログはこんな感じです。

client 127.0.0.1#39784 (a.nsec.dlvtest.dns-oarc.net): query: a.nsec.dlvtest.dns-oarc.net IN TXT +ED (127.0.0.1)
validating @0x7f8a5802a9c0: a.nsec.dlvtest.dns-oarc.net TXT: no valid signature found
validating @0x7f8a5802a9c0: a.nsec.dlvtest.dns-oarc.net TXT: no valid signature found
  validating @0x7f8a58042860: nsec.dlvtest.dns-oarc.net SOA: no valid signature found
  validating @0x7f8a58042860: nsec.dlvtest.dns-oarc.net SOA: no valid signature found
  validating @0x7f8a58042860: a.nsec.dlvtest.dns-oarc.net NSEC: no valid signature found
  validating @0x7f8a58042860: a.nsec.dlvtest.dns-oarc.net NSEC: no valid signature found
  validating @0x7f8a58042860: nsec.dlvtest.dns-oarc.net SOA: no valid signature found
  validating @0x7f8a58042860: nsec.dlvtest.dns-oarc.net SOA: no valid signature found
  validating @0x7f8a58042860: a.nsec.dlvtest.dns-oarc.net NSEC: no valid signature found
  validating @0x7f8a58042860: a.nsec.dlvtest.dns-oarc.net NSEC: no valid signature found
error (no valid RRSIG) resolving 'a.nsec.dlvtest.dns-oarc.net/DS/IN': 192.5.4.1#53
  validating @0x7f8a60056310: nsec.dlvtest.dns-oarc.net SOA: no valid signature found
  validating @0x7f8a60056310: nsec.dlvtest.dns-oarc.net SOA: no valid signature found
  validating @0x7f8a60054670: a.nsec.dlvtest.dns-oarc.net NSEC: no valid signature found
  validating @0x7f8a60054670: a.nsec.dlvtest.dns-oarc.net NSEC: no valid signature found
  validating @0x7f8a60054670: nsec.dlvtest.dns-oarc.net SOA: no valid signature found
  validating @0x7f8a60054670: nsec.dlvtest.dns-oarc.net SOA: no valid signature found
  validating @0x7f8a60054670: a.nsec.dlvtest.dns-oarc.net NSEC: no valid signature found
  validating @0x7f8a60054670: a.nsec.dlvtest.dns-oarc.net NSEC: no valid signature found
error (no valid RRSIG) resolving 'a.nsec.dlvtest.dns-oarc.net/DS/IN': 149.20.58.65#53
error (no valid DS) resolving 'a.nsec.dlvtest.dns-oarc.net/TXT/IN': 149.20.58.65#53
validating @0x7f8a580337d0: a.nsec.dlvtest.dns-oarc.net TXT: no valid signature found
validating @0x7f8a580337d0: a.nsec.dlvtest.dns-oarc.net TXT: no valid signature found
validating @0x7f8a580337d0: a.nsec.dlvtest.dns-oarc.net TXT: bad cache hit (a.nsec.dlvtest.dns-oarc.net/DS)
error (broken trust chain) resolving 'a.nsec.dlvtest.dns-oarc.net/TXT/IN': 192.5.4.1#53

もう一つのレコード、 a.nsec3.dlvtest.dns-oarc.net は両方とも正常に引くことができます。

BIND の設定ファイルには

    dnssec-enable yes;
    dnssec-validation auto;
    dnssec-lookaside auto;

と書いてあります。

正直お手上げです... BIND の挙動がおかしいように思えるんですが、どうなんでしょう。検索してもよくわかりませんでした。

冬コミ申し込みました!

冬コミに申し込みました! サークル名は「低級はっかーズ」です。 Low Level Hackers と読みます。

Linux Kernel のちょっといい話を本にできたらと思ってます。がんばるよ! 内容の予定ですが

  • 最近(3.0以降?)のカーネルの変更点まとめ(ChangeLog や KernelNewbies から、目立つ変更点をまとめてみます)
  • チューニングネタ... 主に sysctl のパラメータの設定について解説したいです。特に TCP/IP 周りについて

結構マニアックな話として、 Linux 3.4 で追加された X32 ABI(64bit モードなんだけどポインタ32bit) や、3.2 で追加された TCP Proportional Rate Reduction (Google が開発した新しい TCP の再送アルゴリズム)のベンチマークや解説を入れようと思います。

予定は未定ですが、がんばります! blog にも一部書いていければいいなぁと思います。よろしくお願いします。