_ unbound だけでなく ldns も先日バージョンが上がって、こちらは暗号アルゴリズムとして ECDSA が使えるようになった(RFC6605)。というわけで、試してみる。
_ …んー、おかしくね? ldns-keygen -a ECDSAP384SHA384 で鍵はふつーに作れたんだけど、その鍵で署名しても NSEC3 が追加されただけで RRSIG がないですよ?
> ldns-signzone -n example.jp Kexample.jp.+014+36289 > cat example.jp.signed example.jp. 86400 IN SOA ns.example.jp. root.example.jp. 1 10800 3600 2419200 1200 example.jp. 86400 IN NS ns.example.jp. example.jp. 86400 IN MX 10 mx.example.jp. example.jp. 86400 IN DNSKEY 257 3 14 AmA7VonYh9QeDWrLoEOdCbH7ZZ2VFnRdR8GykkQk797JZhF5sorCalk1eKsGYgkV1yFMGdk+rVq3sD+n5DCbcSruEP7Ip8OgYIaQe3pBjJDubSpwzempVBZd6qwFIHx5 ;{id = 36289 (ksk), size = 384b} example.jp. 3600 IN NSEC3PARAM 1 0 1 - nbhj5skaq3tn7ccfu04flcfc3cloc6au.example.jp. 1200 IN NSEC3 1 0 1 - lvn0fi3pp40958ekfkcrgqmhheuk8b4o NS SOA MX RRSIG DNSKEY NSEC3PARAM mx.example.jp. 86400 IN A 192.0.2.1 lvn0fi3pp40958ekfkcrgqmhheuk8b4o.example.jp. 1200 IN NSEC3 1 0 1 - nbhj5skaq3tn7ccfu04flcfc3cloc6au A RRSIG_ あー、OpenSSL では 0.9.8 から ECDSA がサポートされてるようなので問題なく使えると思いこんでたんだけど、さらに調べてみたら DNSSEC で使う SHA-256/384 な ECDSA はどうやら 1.0.0 からのサポートのようで、0.9.8 では SHA-1 しか使えないみたい。FreeBSD は最新の 9.0 でも 0.9.8 を使ってるんですが…。ldns のドキュメントには古い openssl の場合は --disable-ecdsa で configure しろ、と書いてあるけど、古いのって具体的にどれよ、というところまでは書いてないんだよなぁ。
_ ということで 1.0.1c を入れて ldns もコンパイルしなおして試してみると、うん、RRSIG がちゃんと生成された。
_ えーと、ecdsa with sha-1 しかサポートしてない openssl 0.9.8 でも鍵の生成が問題なかったのは、鍵生成はハッシュ計算しないので関係ないから、NSEC3 が問題なかったのは NSEC3 は暗号アルゴリズムとか無関係に sha-1 しか使わない (*1)から、ってことであってるかな? sha-256/384 未対応で RRSIG の生成ができないなら、エラーにするか、あるいはそもそも configure の段階で無効にしてくれるとありがたいんだけれど。まあ、ldns についてくるツールはしょせん examples/ ディレクトリの下に存在するものだから多くを望んじゃいけない。…って、この中途半端な ldns を使ってる unbound はもしかして ECDSA に対応してるつもりで実は検証しようとするとコケる状態なのかしら。逆に、署名さえできれば NSEC3 の計算は問題ないので、openssl 0.9.8 でビルドされた権威サーバにゾーンを持っていっても問題ないってことでいいかな?
(*1): 将来のために拡張の余地はあるけど、現在定義されてるのは sha-1 だけ(RFC 5155 section 11)。
_ ちうことで、ECDSA Curve P-256 with SHA-256 (alg=13) な署名をしたゾーンを動かしてみた。せっかくなんで、ついでに ECC-GOST (alg=12) 署名のゾーンもいっしょに。ecdsa.chigumaya.jp と gost.chigumaya.jp でどぞ。AXFR も開放してあります。DNS の結果を眺めるだけのゾーンであって、メールやら web やらそれ以外やらのサービスは一切動いてないので念のため。
_ 今回は鍵長 256bit と 384bit が定義されているうちの弱い方でやったけど、ECDSA は 224bit で RSA 2048bit と同等の強度らしいので、弱い方でも RSA 鍵のように強度の低い ZSK を毎月ロールオーバーする、なんて運用はせずに年に1回のロールオーバーでも問題なさそう。署名のサイズもかなり小さいので、ロールオーバー中の二重署名状態でのパケット肥大化もそれほど気にする必要がなく、RSA よりも KSK と ZSK を分離する意義は薄い。ので、単一鍵署名でやることにした。DNSKEY を調べても 257 の鍵だけで 256 の ZSK は見えません。
_ ちゃんと対応した validator だと、
てな感じで、alg=13 な RRSIG で ad フラグが立つ。> drill -D ecdsa.chigumaya.jp dnskey ;; ->>HEADER<<- opcode: QUERY, rcode: NOERROR, id: 47849 ;; flags: qr rd ra ad ; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0 ;; QUESTION SECTION: ;; ecdsa.chigumaya.jp. IN DNSKEY ;; ANSWER SECTION: ecdsa.chigumaya.jp. 3170 IN DNSKEY 257 3 13 HC1ChiTJf5bPNiKwf00Ws2yKQK39A4p7Gwfngyot5ilt04a7vZb0GpqSSeVbqmqNOl+ZsTklY2WmxMkazMxc8g== ;{id = 12748 (ksk), size = 256b} ecdsa.chigumaya.jp. 3170 IN RRSIG DNSKEY 13 3 3600 20120713023351 20120603023351 12748 ecdsa.chigumaya.jp. d7UGxVD9wRaczr8AHKRpTbpQAEXPbTBhtGJeDE6wfKmbIT9PKkz36oxmBDfIgtGyvJvx479aJsr6BP7wKyY6zw== (以下略)_ サーバは NSD 3.2.10 だけど、こちらは openssl 0.9.8 で作っていて今回のためにコンパイルしなおしたりはしてないので、GOST も ECDSA with SHA-256/384 も知らない。でも、事前の予想どおり NSEC3 も含めて問題なく動いてるっぽい。
_ unbound 1.4.17 (ecdsa 対応) + ldns 1.6.13 (ecdsa 対応) + openssl 0.9.8 (ecdsa/sha-2 非対応)という中途半端なシロモノをわざわざ用意してみたけど、うまく検証できなくて bogus (SERVFAIL)になるんじゃないかという予想に反して、さりとて secure になる(ad フラグが立つ)はずもなく、つまり署名されてないのと同じ insecure な結果に。そもそも ECDSA をサポートしてない validator と同じ挙動だな。まあ、正しい署名をしてるのに insecure ってことは、世間に広く普及するまでは使う意味がまったくないってことだよな。いや、RSA な DNSSEC だってちっとも普及してないことには変わりないので、将来のアルゴリズムロールオーバーの手間を省くためにいっそはじめから ECDSA という考え方もあるか。
_ なお、テスト用なので飽きたら予告なく消えます。
_ そんなわけで、今回 openssl 1.0.1 を入れたんだが。
あのー、出力形式を勝手に変えないでくれるかな。 うちの DNSSEC スクリプトでは NSEC3 の salt を openssl rand 256 | openssl md5 | cut -c1-8 として作っていたので、1.0.1 にしたら salt が '(stdin)=' なんて妙な文字列になってしまってエラーになった。> echo hoge | /usr/bin/openssl md5 # 0.9.8 c59548c3c576228486a1f0037eb16a1b > echo hoge | /usr/local/bin/openssl md5 # 1.0.1 (stdin)= c59548c3c576228486a1f0037eb16a1b_ MD5 を計算するコマンドは GNU は md5sum、*BSD は md5 と違っていて(しかも *BSD は /sbin/md5 と /bin/md5 の流派がある)、出力フォーマットも両者で異なるので、どちらも使わずどの環境でも同じように使える openssl で計算してたのに、同じコマンド名なのに出力が違うとかまじやめてくれ。スクリプトの中から MD5 の比較をするとかよくある使い方なのに、出力が変わるとスクリプトをいちいち修正しなきゃいけなくなる。ポータブルなスクリプトを書こうとした場合にはかなり困るぞ。
_ 今回の場合は MD5 の値に意味があるわけではなく、てきとーな16進値が欲しかっただけなので hexdump -e '"%x"' として逃げたけど。hexdump の書式指定ってキモいよね…。
_ これがあると夏が来た、って感じがするよね。今年はちょっと早いけど。毎年恒例、夏の BIND 脆弱性祭。
_ つーか、まじでカンベンしてください。たいていは穴があっても権威サーバか参照サーバかどっちか対処すればいいだけなのに、今回は両方だし。まあ、dnssec をやってなかったり、信頼できる master だけとやりとりする slave であれば権威サーバは放置できるけど。