前の5件 | -
某ブログのECCとRSAのハイブリッド設定を試してみる
このツイートがリツイートで流れてきて、ここを見たんだが、なんだか書いていることが変な気がする。
とはいうもののここでいうハイブリッドな設定は2.2系でしか試したことがないので2.4系の場合なんともなのだが、取り敢えず、ドキュメントを見る限り、記載のディレクティブの説明は変わっていない模様。まあ、ドキュメントが実装に追いついていない場合もあるだろうし、兎も角、百聞は一試しに如かずということで試してみた。結論から言えば
ちなみに、お試し環境は
で、結果ですが、
となっている場合、
の両方が
こういう場合、
ただ、
いずれにせよ、このあたりがECC対応になっているのってシマンテック絡んだ話ですよね。まあ、ここはnginxなので記事の設定ではないのでしょうけど、同じ会社のサイトのKumonos(クモノス)なんかは間違った設定になっておらず、ちゃんと設定されているんですよね。
これって、一体何の罠?
とはいうもののここでいうハイブリッドな設定は2.2系でしか試したことがないので2.4系の場合なんともなのだが、取り敢えず、ドキュメントを見る限り、記載のディレクティブの説明は変わっていない模様。まあ、ドキュメントが実装に追いついていない場合もあるだろうし、兎も角、百聞は一試しに如かずということで試してみた。結論から言えば
SSLCertificateChainFile
を2行以上記載する意味はない。ちなみに、お試し環境は
FreeBSD 9.1-RELEASE-p7
に、ports
からApache
は2.4.6
を、OpenSSL
は1.0.1e
を入れて試してみました。証明書は自前でルートCAと中間CAを作ってサーバー証明書を発行した次第です。具体的にいえば、CA.pl
とopenssl.cnf
をごにょごにょ弄ってECCとRSAの独立したチェーンを作成しました。確認は、s_client(1)
に-cipher
付けて返される証明書を調整して-showcerts
で送付されてくる証明書を見たりして確認してます。で、結果ですが、
SSLCertificateChainFile
を2行以上書くと、一番最後に書いたものだけが有効になるようです。まあ、何か他のモジュール入れたりパッチ当てたりしたら複数行書けるのかもしれないですけど、取り敢えず、上記お試し環境では最後の行しか使われませんでした。つまり、ここのように131: SSLCertificateChainFile "/usr/local/ssl/ecc_ca.crt"
132: SSLCertificateChainFile "/usr/local/ssl/rsa_ca.crt"
となっている場合、
/usr/local/ssl/rsa_ca.crt
のものしか使われないということです。Server Certificate
で送付されてくる証明書は、SSLCertificateFile
に指定したものに続けてSSLCertificateChainFile
に指定したものになりますが、108: SSLCertificateFile "/usr/local/ssl/ecc_ssl.crt"
109: SSLCertificateFile "/usr/local/ssl/rsa_ssl.crt"
の両方が
/usr/local/ssl/rsa_ca.crt
に対応する秘密鍵で署名されているなら問題ないですが、異なる場合、サーバー側がハンドシェイクによって選択されるアルゴリズムによってはServer Certificate
で送付されてくる証明書のチェーンが繋がらないことになります。ただ、ブラウザ側で中間証明書まで含めて保持している場合は問題ないですが、それを前提にするなら中間証明書の設定なんて要らないですね。こういう場合、
SSLCertificateChainFile
に複数の中間証明書を数珠つなぎで記載してやっても、それがそのまま繋がって送付されてくるのでブラウザ側でチェーンをつなげてくれる場合が多いかと思いますが、サーバー証明書に対応するチェーンの分だけ選択して送付したいならば、SSLCACertificatePath
かSSLCACertificateFile
に中間証明書を指定してやればよいです。SSLCACertificatePath
の場合、指定したディレクトリに各中間証明書を各々独立した拡張子.pem
なファイル記載して、c_rehash
スクリプトでも実行してやってハッシュ値からのリンクを貼ってやればよいですし、SSLCACertificateFile
の場合、中間証明書を数珠つなぎに書いてやればよいです。ただ、
SSLCACertificatePath
もSSLCACertificateFile
もクライアント認証する際に使われるものですので、クライアント認証する際はそこに記載するべき証明書も変わってくる可能性がありますので、そのあたりは問題が生じるかもしれません。また、チェーンの繋がったルート証明書もそこに配置するとServer Certificate
でそれも繋げて送付してきますので、無駄といえば無駄ですね。いずれにせよ、このあたりがECC対応になっているのってシマンテック絡んだ話ですよね。まあ、ここはnginxなので記事の設定ではないのでしょうけど、同じ会社のサイトのKumonos(クモノス)なんかは間違った設定になっておらず、ちゃんと設定されているんですよね。
これって、一体何の罠?
DANEのTLSA RRのCertificate Association Data部をopenssl(1)で出力してみる
DNSSEC and Certificatesを見て、いろんな
hash-slingerとかGnuTLSの
まず、
要するに、
ちなみに、
以上を踏まえて作っていくことに。以下、
として、この値から
みたいな感じにします。
取り敢えず、
として、得られた
とすれば
といった感じになります。
後は、
とすれば
といった感じに。
とすれば
といった感じになります。
直接関係ないですけど、DANE Test Sitesのhttps://www.nlnetlabs.nl/の
ワイルドカードな証明書持ってて、メールとかにも併用してたりする場合なんかには便利な書き方かも。
Selector
やMatching Type
でTLSA RR
のCertificate Association Data Field
の出力方法をメモっておこうと思った次第。hash-slingerとかGnuTLSの
danetool
とか使えば一撃なんでしょうけど、そこはなるべく普通に入っていそうなもんでなんとかしようかといったところです。まず、
TLSA RR
の例は、RFC6698によると以下のような感じです。https://www.example.com/
用の場合ですかね。_443._tcp.www.example.com. IN TLSA (
0 0 1 d2abde240d7cd3ee6b4b28c54df034b9
7983a1d16e8a410e4561cb106618e971 )
要するに、
d2abde240d7cd3e...
なところを主にopenssl(1)
でも使って出力していこうかという話。ちなみに、
0 0 1
なところはRFC6698によると、順に、Certificate Usage Field
、Selector Field
、Matching Type Field
だそうです。Certificate Usage Field
は0~3までが目的が決まっているようで、私のような下々の人々が使うのは1か3でしょうか。1はCAから発行された証明書なんかのときに、3はオレオレなんかのときに使います。正確にはPKIX certification path validation
にパスすることが必須の場合は1で、不要な場合は3ですので、CAからちゃんと発行された証明書でも別にPKIX certification path validation
不要なら3にしても構わないかと思います。尚、0はCAなんかの証明書で2はトラストアンカーといったところかと思われます。以下、Certificate Usage Field
は3で記載していきます。Selector Field
は0か1で、0がFull certificate
、1がSubjectPublicKeyInfo
。ざっくり要約してしまえば、証明書全体か公開鍵部分かといったところです。Matching Type Field
は0~2で、0がSelector Field
で指定したもの全体、1がそのSHA-256
、2がそのSHA-512
です。以上を踏まえて作っていくことに。以下、
server.crt
をPEMなX.509証明書とします。Selector Field
が0で、Matching Type Field
が1の場合。$ openssl x509 -in server.crt -inform PEM \
-outform DER | openssl dgst -sha256
(stdin)= 11ac76469b7d60019acb39109caef2954ffdfe8a3155e1f143f088db8ce4421b
として、この値から
TLSA RR
は、_443._tcp.www.example.jp. 86400 IN TLSA 3 0 1 11ac76469b7d60019acb39109caef2954ffdfe8a3155e1f143f088db8ce4421b
みたいな感じにします。
Selector Field
が0で、Matching Type Field
が2の場合は、-sha256
のところを-sha512
にして、3 0 1
のところを3 0 2
にします。取り敢えず、
Matching Type Field
が0の場合は後回しにして、Selector Field
が1で、Matching Type Field
が1の場合。証明書から公開鍵を取り出してそれをDERエンコードで出力してやって、SHA-256
を取ればよいから、$ openssl x509 -in server.crt -inform PEM -pubkey \
-noout | openssl asn1parse -out subject.der -noout
として、得られた
subject.der
を$ openssl dgst -sha256 subject.der
SHA256(subject.der)= ae3b460d3cae8d5596896485a0df58ea22af8a8a75066f045c4b88e47cf55ae1
とすれば
Certificate Association Data Field
値が得られますので、TLSA RR
は、_443._tcp.www.example.jp. 86400 IN TLSA 3 1 1 ae3b460d3cae8d5596896485a0df58ea22af8a8a75066f045c4b88e47cf55ae1
といった感じになります。
Selector Field
が1で、Matching Type Field
が2の場合は、-sha256
のところを-sha512
にして、3 1 1
のところを3 1 2
にします。後は、
Matching Type Field
が0の場合。あんまり使わないと思いますけど一応書いておこうかと。Selector Field
が0の場合は、$ openssl x509 -in server.crt -inform PEM \
-outform DER | hexdump -e '4/1 "%02x"'
308203f53082035ea003020102020313f...
とすれば
Certificate Association Data Field
値が得られますので、TLSA RR
は、_443._tcp.www.example.jp. 86400 IN TLSA 3 0 0 308203f53082035ea003020102020313f...
といった感じに。
Matching Type Field
が0でSelector Field
が1の場合は、先に作ったsubject.der
に対して、$ hexdump -e '4/1 "%02x"' subject.der
30820122300d06092a864886f...
とすれば
Certificate Association Data Field
値が得られますので、TLSA RR
は、_443._tcp.www.example.jp. 86400 IN TLSA 3 1 0 30820122300d06092a864886f...
といった感じになります。
hexdump -e '4/1 "%02x"' subject.der
は、hexdump(1)
の代わりにod(1)
、awk(1)
、tr(1)
を使って、od -t x1 subject.der | awk '{$1="";print}' | tr -d " \t\r\n"
としてもいけるかと思います。もっとうまいやり方があるのかもしれませんけど。もっと良さげなオプションとかあれば教えて誰か教えて頂けると幸い。後、長すぎる場合は、()付けてmulti-line formatにするとかして工夫した方がいいのかもしれません。直接関係ないですけど、DANE Test Sitesのhttps://www.nlnetlabs.nl/の
TLSA RR
を参照すると以下のような出力が。$ dig +dnssec +multi +noall +answer _443._tcp.www.nlnetlabs.nl. tlsa @127.0.0.1
_443._tcp.www.nlnetlabs.nl. 10166 IN CNAME 3.1.1._dane.nlnetlabs.nl.
_443._tcp.www.nlnetlabs.nl. 10166 IN RRSIG CNAME 8 5 10200 (
20121112005005 20121015005005 42393 nlnetlabs.nl.
AdqZ9MBS/LWP2y7X08F6vqB8207/bwty0GyCVDkUV3XP
ZsKyfUXBDvSLn69JpN9lTM+GndCCYABgNy2VJ6XApiKu
R1lwql8EHj+0e8VDxxZATVUFFy5XhnFbtoP1p8zEMXRr
TjJ4qAmgP0hmj91QkhVrll93PJM8H7c1rikpT6A= )
3.1.1._dane.nlnetlabs.nl. 10166 IN TLSA 3 1 1 (
0D1FCBD71686199607A132744A4918FC209565C91FA8
E9FFEEA0AAFD6B9305F6 )
3.1.1._dane.nlnetlabs.nl. 10166 IN RRSIG TLSA 8 6 10200 (
20121112005003 20121015005003 42393 nlnetlabs.nl.
GITh2HgD1va3ctKoEAoJ5YJmV5FpBTN5kjgxi4DX0QLq
/+DxQ3+yLj3HReTbmRKgVaeKImpOg9wEuJEkO8b3co5J
RrJOxO2sS542oN46y5zaZrk3OH78tofTx22axdIPgdRm
Uxn+wQheL/tDRDoFdmsdqYbneiBWz+yh5pM3QaY= )
ワイルドカードな証明書持ってて、メールとかにも併用してたりする場合なんかには便利な書き方かも。
BIND9.8.0rc1でDNS64を使ってみる
BIND-9.8.0rc1で
IPv6のみのホストがIPv4のホストにアクセスする場合に、IPv6セグメントとIPv4セグメントの間にNAT64サーバーという変換機能付ゲートウェイを設置してアクセスを可能にする仕組みがあるようですが、その際、DNSがIPv4ホストのAを返してもIPv6セグメントでは海を車で渡れと言われているようなもので使えないので、エンドポイントとなるNAT64サーバーのインターフェースへの繋ぎとなるAAAAをある規則に従って合成して返すのがDNS64の役割みたいです。
のように書くようです。合成変換するフォーマットについての詳細はRFC6052を参照することになりますが、
ちなみに、
上記具体例の設定で
のAAAAを問い合わせると
となるようです。変換後のTTLはネガティブキャッシュのものとなるようです。
dns64
を試したメモ。IPv6のみのホストがIPv4のホストにアクセスする場合に、IPv6セグメントとIPv4セグメントの間にNAT64サーバーという変換機能付ゲートウェイを設置してアクセスを可能にする仕組みがあるようですが、その際、DNSがIPv4ホストのAを返してもIPv6セグメントでは海を車で渡れと言われているようなもので使えないので、エンドポイントとなるNAT64サーバーのインターフェースへの繋ぎとなるAAAAをある規則に従って合成して返すのがDNS64の役割みたいです。
named.conf
に記載するdns64
ディレクティブは、そのAから合成変換したAAAAを作る作り方みたいなものを定義するもので、options
とview
に書けるみたいです。具体的には、acl rfc1918 { 10/8; 192.168/16; 172.16/12; };
...
dns64 64:FF9B::/96 {
clients {
2001:BD8:0:1::/64;
};
mapped { !rfc1918; any; };
exclude { 64:FF9B::/96; ::ffff:0000:0000/96; };
suffix ::;
recursive-only yes;
break-dnssec yes;
};
dns64-server "dns64.example.jp.";
dns64-contact "hostmaster.example.jp.";
のように書くようです。合成変換するフォーマットについての詳細はRFC6052を参照することになりますが、
dns64
の後の64:FF9B::/96
のところにIPv6-prefix
を定義します。これは合成変換後のAAAAのプレフィックスになります。残りのものについては以下に列挙します。clients
…合成変換したAAAAを返す対象となるクライアントを定義します。デフォルトはany;
です。mapped
…合成変換の対象となるA RRの値を定義します。デフォルトはany;
です。exclude
…合成変換が適用されたアドレスかどうかの判定から除外するアドレスを記載します。suffix
…RFC6052の2.2.IPv4-Embedded IPv6 Address Formatに記載されているprefixが96以外のときにsuffixにはめ込む値を定義します。例えば、prefixが64:FF9B::/40
でsuffixが::1f2a
で変換対象のAが192.0.2.2
だとすると、変換後のAAAAは64:ff9b:c0:2:2::1f2a
になります。recursive-only
…RDビットが起っている問い合わせのみに変換後のAAAAを返すかどうかを定義します。つまりyes
にすると再帰クエリーの場合に変換後のAAAAを返します。break-dnssec
…DNSSECの問い合わせに対してAAAAを返すかどうかを定義します。no
にするとAにDNSSECの署名がある場合にDOビットをセットした問い合わせを行うと変換後のAAAAを返しません。yes
にすると変換対象とします。当然ですが変換後のAAAAに署名は付きません。といいますか付けることができません。dns64-server
…prefixに対するIP6.ARPA.
のマスターサーバーの値を定義します。例えば、prefixが64:FF9B::/32
の場合にb.9.f.f.4.6.0.0.ip6.arpa.
のSOAを問い合わせると、マスターサーバーのところにここに定義した値が入ります。dns64-contact
…prefixに対するIP6.ARPA.
の管理者メールアドレスの値を定義します。dns64-server
の例と合わせて具体的なSOAの値を記載すると以下のようになります。b.9.f.f.4.6.0.0.ip6.arpa. 86400 IN SOA dns64.example.jp. hostmaster.example.jp. 0 28800 7200 604800 86400
ちなみに、
dns64
は複数記載してクライアント毎にprefixを変えたりできるようです。上記具体例の設定で
host.example.jp. 86400 IN A 192.0.2.2
のAAAAを問い合わせると
host.example.jp. 10800 IN AAAA 64:ff9b::c000:202
となるようです。変換後のTTLはネガティブキャッシュのものとなるようです。
ISC DLVからDS方式の移行
JPRSがJPドメイン名サービスにDNSSECを導入したことに伴いISC DLVからJPRS上のDS方式に移行したので、そのメモでもと。尚、他の関連ネタ同様、ここなんかに書いている
まず、新しいKSKを作ります。ISC DLVで使っていたものをそのまま移行でもよいのでしょうけど、折角だしこの機会に切り替えた方がよいかと思いまして。使用期間もわかりやすいかと思いますし。まあ、ゴタクは兎も角、新しいKSK作ります。
KSKのロールオーバー方式ですが、こことかここに2重署名方式(Double Signature)とありますので、それに準じてみたいと思います。とはいうものの、そもそも登録しているところが違うので意味合いが変わって来ている感はありますが、まあ、似たような感じでやったと思って頂ければ。まず、publishedになってからactiveにするまでの時間ですが、DNSKEYのTTLとゾーン転送にかかる時間と誤差程度の作業時間(例えば、鍵作ってから実際に公開するまでの時間とか)ぐらいみればいいわけですが、TTLはまあ一般的には1日ぐらいだと思いますし、ゾーン転送は最近は
で、これで、鍵が出来ているはずなので、
とします。で、作成した
レジストラにもよるのでしょうけど、利用中の名づけてねっとでは鍵ID以降、つまり、
をフォームに貼り付ける方式でした。まあ、このあたりは利用中のレジストラのやり方に従えばよいだけかと思います。
親のゾーン(この場合はjp)にDS RRが登録されるのを待ちます。jp.のNS RRは、
なんぞで得られると思いますし、それらに
等とすれば確認はできるかと思います。確認できたら、ISC DLVからDLV RRを消します。Zone Actionsの(delete)をぽちっとするだけです。ここで、また、DLV RRのTTLとゾーン転送にかかる時間程度を待つことになりますが、TTLが3600、Refreshが7200のようなので、3, 4時間程度待てばよいでしょう。その後、古いKSKがKexample.jp.+008+12199だったとしますと、
とします。その後、
とすればゾーンから古いKSKは消えてくれます。(*1)。
*1: 別に
auto-dnssec maintain;
が前提になっています。auto-dnssec maintain;
についてはBIND97付属のARMの他、これなんかも参考になりそうです。まず、新しいKSKを作ります。ISC DLVで使っていたものをそのまま移行でもよいのでしょうけど、折角だしこの機会に切り替えた方がよいかと思いまして。使用期間もわかりやすいかと思いますし。まあ、ゴタクは兎も角、新しいKSK作ります。
$ su -
# su - named --shell=/bin/bash
$ /usr/sbin/dnssec-keygen -f KSK -r /dev/urandom -3 -a \
RSASHA256 -b 2048 -P now -A now+30h -I now+13mo -D now+13mo \
-K /var/named/chroot/var/named/keys/example.jp \
-n ZONE example.jp
Generating key pair...
Kexample.jp.+008+02746
KSKのロールオーバー方式ですが、こことかここに2重署名方式(Double Signature)とありますので、それに準じてみたいと思います。とはいうものの、そもそも登録しているところが違うので意味合いが変わって来ている感はありますが、まあ、似たような感じでやったと思って頂ければ。まず、publishedになってからactiveにするまでの時間ですが、DNSKEYのTTLとゾーン転送にかかる時間と誤差程度の作業時間(例えば、鍵作ってから実際に公開するまでの時間とか)ぐらいみればいいわけですが、TTLはまあ一般的には1日ぐらいだと思いますし、ゾーン転送は最近は
NOTIFY
とかあるのでそんなに掛からないとは思えども、普通に転送する場合とか失敗する場合とかも考えて多めに見積もって6時間ぐらいみておけばいいかなということで30時間としています。retiredとdeletedはどうせ更新時に明示的に行うことなので、ちょっと長めに適当です。で、これで、鍵が出来ているはずなので、
$ rndc loadkeys example.jp.
とします。で、作成した
Kexample.jp.+008+02746
でDNSKEYの署名が開始されるまで待ちます。要するに30時間後です。署名が開始されたらDSを申請します。dnssec-dsfromkey(8)
を使ってDS RRを得ます。$ /usr/sbin/dnssec-dsfromkey \
/var/named/chroot/var/named/keys/example.jp/Kexample.jp.+008+02746.key
example.jp. IN DS 2746 8 1 1D8F72D56BEA0EABA6E6BCAC2093906135C9457B
example.jp. IN DS 2746 8 2 C6884BFF053E0F63B00153411AD3873DCD9462CBDD1261707CA83F2B 762319F7
レジストラにもよるのでしょうけど、利用中の名づけてねっとでは鍵ID以降、つまり、
2746 8 1 1D8F72D56BEA0EABA6E6BCAC2093906135C9457B
2746 8 2 C6884BFF053E0F63B00153411AD3873DCD9462CBDD1261707CA83F2B 762319F7
をフォームに貼り付ける方式でした。まあ、このあたりは利用中のレジストラのやり方に従えばよいだけかと思います。
親のゾーン(この場合はjp)にDS RRが登録されるのを待ちます。jp.のNS RRは、
$ dig jp. ns
なんぞで得られると思いますし、それらに
$ dig +norec @a.dns.jp example.jp. ds
等とすれば確認はできるかと思います。確認できたら、ISC DLVからDLV RRを消します。Zone Actionsの(delete)をぽちっとするだけです。ここで、また、DLV RRのTTLとゾーン転送にかかる時間程度を待つことになりますが、TTLが3600、Refreshが7200のようなので、3, 4時間程度待てばよいでしょう。その後、古いKSKがKexample.jp.+008+12199だったとしますと、
dnssec-settime(8)
使って、$ /usr/sbin/dnssec-settime -I now \
/var/named/chroot/var/named/keys/example.jp/Kexample.jp.+008+12199
$ rndc loadkeys example.jp.
とします。その後、
$ /usr/sbin/dnssec-settime -D now \
/var/named/chroot/var/named/keys/example.jp/Kexample.jp.+008+12199
$ rndc loadkeys example.jp.
とすればゾーンから古いKSKは消えてくれます。(*1)。
*1: 別に
-I
と-D
を一気にやってしまってもいいのですが、なんとなくかわいそうな気がするものでw
NSEC3PARAMをCRON(8)で更新する(DNSSECネタ)
ネタ的には「auto-dnssec maintain; を試してみる」あたりの設定が前提です。
まず、以下のようなスクリプトを作ります。なるべく通常インストールされてそうなコマンドに限定して書いたつもり。
スクリプトは
言うまでもないですが
まず、以下のようなスクリプトを作ります。なるべく通常インストールされてそうなコマンドに限定して書いたつもり。
$ su -
# cd /var/named
# mkdir bin
# chown -R named:named bin
# su - named --shell=/bin/bash
$ cd bin
$ cat > update-nsec3param.sh
#!/bin/sh
RETVAL=0
usage () {
echo $"Usage: $0 -s server_ip_address -d zone_name" 1>&2
RETVAL=1
}
OPT=""
DOMAIN=""
SERVER=""
while getopts s:d: OPT
do
case $OPT in
d) DOMAIN=$OPTARG
;;
s) SERVER=$OPTARG
;;
\?) usage
exit $RETVAL
;;
esac
done
shift `expr $OPTIND - 1`
if [ -z "$DOMAIN" ]; then
usage
exit $RETVAL
fi
if [ -z "$SERVER" ]; then
usage
exit $RETVAL
fi
ITER=$((RANDOM % 6 + 5))
LEN=$((RANDOM % 16 + 3))
HASH=`/usr/bin/openssl rand $LEN | /usr/bin/hexdump -e '1/1 "%02x"'`
cat << UFILE
server $SERVER
update delete $DOMAIN. IN NSEC3PARAM
update add $DOMAIN. 0 IN NSEC3PARAM 1 0 $ITER $HASH
send
UFILE
exit 0
スクリプトは
openssl(1)
とhexdump(1)
がインストールされていることを前提にしてます。salt
の長さやiterations
の回数は適当です。まあ、長すぎず短すぎない程度にした感じ。nsupdate(1)
を受け付けてくれるIPアドレスを192.0.2.2
、更新対象のゾーンをexample.jp
と仮にでもしておきます。crontab -e
とかして以下のような行を追加します。10 3 1,11,21 * * /var/named/bin/update-nsec3param.sh \
-s 192.0.2.2 -d example.jp \
| /usr/bin/nsupdate \
-k /var/named/chroot/var/run/named/session.key \
> /dev/null 2>&1
言うまでもないですが
\
は継続行の意味です。これで毎月1日11日21日の3時10分頃にNSEC3PARAM
を更新してくれるはず。
前の5件 | -