SSブログ
前の5件 | -

某ブログのECCとRSAのハイブリッド設定を試してみる

このツイートがリツイートで流れてきて、ここを見たんだが、なんだか書いていることが変な気がする。

とはいうもののここでいうハイブリッドな設定は2.2系でしか試したことがないので2.4系の場合なんともなのだが、取り敢えず、ドキュメントを見る限り、記載のディレクティブの説明は変わっていない模様。まあ、ドキュメントが実装に追いついていない場合もあるだろうし、兎も角、百聞は一試しに如かずということで試してみた。結論から言えばSSLCertificateChainFileを2行以上記載する意味はない。

ちなみに、お試し環境はFreeBSD 9.1-RELEASE-p7に、portsからApache2.4.6を、OpenSSL1.0.1eを入れて試してみました。証明書は自前でルートCAと中間CAを作ってサーバー証明書を発行した次第です。具体的にいえば、CA.plopenssl.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に複数の中間証明書を数珠つなぎで記載してやっても、それがそのまま繋がって送付されてくるのでブラウザ側でチェーンをつなげてくれる場合が多いかと思いますが、サーバー証明書に対応するチェーンの分だけ選択して送付したいならば、SSLCACertificatePathSSLCACertificateFileに中間証明書を指定してやればよいです。

SSLCACertificatePathの場合、指定したディレクトリに各中間証明書を各々独立した拡張子.pemなファイル記載して、c_rehashスクリプトでも実行してやってハッシュ値からのリンクを貼ってやればよいですし、SSLCACertificateFileの場合、中間証明書を数珠つなぎに書いてやればよいです。

ただ、SSLCACertificatePathSSLCACertificateFileもクライアント認証する際に使われるものですので、クライアント認証する際はそこに記載するべき証明書も変わってくる可能性がありますので、そのあたりは問題が生じるかもしれません。また、チェーンの繋がったルート証明書もそこに配置するとServer Certificateでそれも繋げて送付してきますので、無駄といえば無駄ですね。

いずれにせよ、このあたりがECC対応になっているのってシマンテック絡んだ話ですよね。まあ、ここはnginxなので記事の設定ではないのでしょうけど、同じ会社のサイトのKumonos(クモノス)なんかは間違った設定になっておらず、ちゃんと設定されているんですよね。

これって、一体何の罠?

nice!(0)  コメント(0)  トラックバック(0) 
共通テーマ:日記・雑感

DANEのTLSA RRのCertificate Association Data部をopenssl(1)で出力してみる

DNSSEC and Certificatesを見て、いろんなSelectorMatching TypeTLSA RRCertificate Association Data Fieldの出力方法をメモっておこうと思った次第。

hash-slingerとかGnuTLSdanetoolとか使えば一撃なんでしょうけど、そこはなるべく普通に入っていそうなもんでなんとかしようかといったところです。

まず、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 FieldSelector FieldMatching 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 Siteshttps://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.0rc1dns64を試したメモ。

IPv6のみのホストがIPv4のホストにアクセスする場合に、IPv6セグメントとIPv4セグメントの間にNAT64サーバーという変換機能付ゲートウェイを設置してアクセスを可能にする仕組みがあるようですが、その際、DNSがIPv4ホストのAを返してもIPv6セグメントでは海を車で渡れと言われているようなもので使えないので、エンドポイントとなるNAT64サーバーのインターフェースへの繋ぎとなるAAAAをある規則に従って合成して返すのがDNS64の役割みたいです。

named.confに記載するdns64ディレクティブは、そのAから合成変換したAAAAを作る作り方みたいなものを定義するもので、optionsviewに書けるみたいです。具体的には、
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…合成変換が適用されたアドレスかどうかの判定から除外するアドレスを記載します。
  • suffixRFC6052の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はネガティブキャッシュのものとなるようです。
nice!(0)  コメント(0)  トラックバック(0) 
共通テーマ:日記・雑感

ISC DLVからDS方式の移行

JPRSがJPドメイン名サービスにDNSSECを導入したことに伴いISC DLVからJPRS上のDS方式に移行したので、そのメモでもと。尚、他の関連ネタ同様、ここなんかに書いている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
nice!(0)  コメント(1)  トラックバック(0) 
共通テーマ:日記・雑感

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を更新してくれるはず。
nice!(0)  コメント(0)  トラックバック(0) 
共通テーマ:日記・雑感
前の5件 | -

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。