_ 雨ってイヤね。
_ SoftHSM をインストール。手順略。
_ openssl の pkcs#11 engineをインストール。freebsd なので ports/security/engine_pkcs11 を入れるだけ。テスト。
% openssl engine dynamic -pre SO_PATH:/usr/local/lib/engines/engine_pkcs11.so -pre ID:pkcs11 -pre LIST_ADD:1 -pre LOAD -pre MODULE_PATH:/usr/local/lib/libsofthsm.so -t (dynamic) Dynamic engine loading support [Success]: SO_PATH:/usr/local/lib/engines/engine_pkcs11.so [Success]: ID:pkcs11 [Success]: LIST_ADD:1 [Success]: LOAD [Success]: MODULE_PATH:/usr/local/lib/libsofthsm.so Loaded: (pkcs11) pkcs11 engine [ available ]_ openssl の設定ファイルを書く。
もっかいテスト。# vi /etc/ssl/openssl.cnf openssl_conf = openssl_def [openssl_def] engines = engine_section [engine_section] pkcs11 = pkcs11_section [pkcs11_section] engine_id = pkcs11 dynamic_path = /usr/local/lib/engines/engine_pkcs11.so MODULE_PATH = /usr/local/lib/libsofthsm.so init = 0% openssl engine pkcs11 -t (pkcs11) pkcs11 engine [ available ]_ BIND をコンパイル。
% ./configure --with-pkcs11=/usr/local/lib/libsofthsm.so --other-options % vi bin/pkcs11/Makefile #LIBS = -ldl ←コメントアウト % make_ SoftHSM 初期化。
今後 PIN を聞かれたら user PIN の方を答える。SO (security officer) PIN の出番はよくわからん。# softhsm --init-token 0 --slot 0 --label softhsm The SO PIN must have a length between 4 and 255 characters. Enter SO PIN: The user PIN must have a length between 4 and 255 characters. Enter user PIN: The token has been initialized._ HSM 内に鍵を生成する。
HSM 内の鍵のリスト。# pkcs11-keygen -l hoge -b 2048 Enter Pin:鍵を消す。# pkcs11-list Enter Pin: object[0]: handle 2 class 2 label[4] 'hoge' id[0] object[1]: handle 1 class 3 label[4] 'hoge' id[0]# pkcs11-destroy -l hoge label hoge Enter Pin: object[0]: class 2 label 'hoge' id[0] object[1]: class 3 label 'hoge' id[0] sleeping 5 seconds... ←なぜ5秒寝る?_ あらためて、dnssec で使えるような鍵を作成する。
この鍵を dnssec-signzone で使えるようする。# pkcs11-keygen -l ksk -i 1000 -b 2048 Enter Pin: # pkcs11-keygen -l zsk -i 2000 -b 1024 Enter Pin:dnssec-keyfromlabel の -l で指定するラベルは <slot>:<id> の形式。slot は SoftHSM のスロットで、pkcs11-keygen の -s で指定した値(今回は指定してないのでデフォルトの 0)。id は pkcs11-keygen の -i で指定した10進数を16進数に変換したもの。pkcs11-keygen の -l で指定したラベルをそのまま指定するとエラーになる。2時間悩んだ。こんなのわかるかよ。# dnssec-keyfromlabel -l 0:07d0 -f KSK -a RSASHA256 example.com Kexample.com.+008+52822 # dnssec-keyfromlabel -l 0:03e8 -a RSASHA256 example.com Kexample.com.+008+31878_ で、生成された秘密鍵。
鍵の本体は HSM にあるので、ふつーに dnssec-keygen で生成した場合に比べて情報が少ない。上の Engine、Label の値を base64 デコードするとそれぞれ pkcs11、0:07d0 となり、鍵といってもよーするに HSM へのポインタでしかない。# cat Kexample.com.+008+52822.private Private-key-format: v1.3 Algorithm: 8 (RSASHA256) Modulus: 4WZPMs2QxB6lOqdDaKu1pPfmv9bFvIq2wuW6SZnYXtMg77xiqd4D2BnZV85NIfQ6yaTc518UwGVE8F1kKaPd0wb/gd1jP8jXCq57IomGV1NjEoQzbSiRLZVRowDB2W62AanFg3PgC5CAcamy0KXlTiPFC5y+tHYvFGRF+plfhXM= PublicExponent: AQAB Engine: cGtjczExAA== Label: MDowN2QwAA== Created: 20120414044747 Publish: 20120414044747 Activate: 20120414044747_ 署名してみる。
エラーになった。引数は間違ってないはずなんだが。わけわからん。ぐぐってみると、 同じエラーに遭遇した人がいるけど解決してないっぽいな…。# dnssec-signzone -o example.com -k Kexample.com.+008+31878.private example.com Kexample.com.+008+52822.private dnssec-signzone: fatal: cannot sign zone with non-private dnskey Kexample.com.+008+52822.private_ dnssec-keyfromlabel ではなく、SoftHSM のコマンドを使って鍵を作ることも可能ではある。
この場合、生成される鍵は dnssec-keygen で作るのと同じ秘密の情報が含まれたもので、これなら署名も問題なくおこなえる。が、そういうセンシティブな情報を扱いたくないから HSM でブラックボックス化するわけであって、いちいち取り出して使うのなら HSM を使う意味なんてないよね…。それじゃ単なる乱数生成器と変わらん(しかもどうせ /dev/random なので質も速度も向上しない)。# softhsm --export hoge.pem --slot 0 --id 07d0 --pin hogehoge # softhsm-keyconv --tobind --in hoge.pem --name example.com. --ksk --algorithm RSASHA256_ ちなみに、以上の手順は ARM の 4.11 節で解説されているやりかたとはまったく異なる。こっちの手順だと OpenSSL にパッチを当ててコンパイルするところから始めるんだけど、それで作った openssl ではなぜか pkcs11 エンジンが有効にならないので先に進めない。
_ そういうわけで、結論。うごきませんでした。
_ ARM の手順で openssl にパッチを当てたもので pkcs#11 エンジンが有効にならない理由がやっとわかった。平ユーザで openssl から SoftHSM に接続できないかららしい。root でやると通る。たったこれだけのことで半日潰した。 きのうの ARM に従わない方法だとエンジンが有効かどうかの確認は root でなくても可能なんだが。たぶん libsofthsm をリンクするだけで終わりか、その後実際に SoftHSM に接続しにいくかの違いってことだと思う。いや、たしかに SoftHSM が管理してる sqlite DB の権限からして root 以外不可なのは当たり前なんだけどさ、openssl がサポートしてるエンジン種別を確認するだけのコマンドを実行して実際にデバイスにアクセスしにいくとは思わんでしょふつー。
_ ということで、もう一度 ARM の手順にしたがってやってみる。ところで ARM が何のことかわからない、どこにあるかわからないって人はいないよね?
_ openssl にパッチを当てる。
いくつか失敗してるので手で修正する。どう直せばいいかは見ればすぐわかる。% tar xvf openssl-1.0.1.tar.gz % tar xvf bind-9.9.0.tar.gz % cd openssl-1.0.1 % patch -p1 < ../bind-9.9.0/bin/pkcs11/openssl-1.0.0f-patch % find . -name '*.rej' ./crypto/engine/Makefile.rej ./util/mk1mf.pl.rej ./util/mkdef.pl.rej ./Configure.rej_ コンパイル。
コケる。crypto/engine/hw_pk11.c の #define SOLARIS_AES_CTR の行をコメントアウトすると通るが、ほんとにこれであってるのかは知らない。完了したらちゃんと pkcs#11 が使えるようになってるかどうか確認する。root で。さらに、SoftHSM の初期化が済んでないとコケると思う、たぶん。% ./Configure --prefix=/usr/local/bind99 --pk11-libname=/usr/local/lib/libsofthsm.so --pk11-flavor=sign-only -pthread BSD-x86-elf shared % makeいやー、ここまで長かった。というか、確認の方法がまずかっただけで、できたものに問題はなかったということか。うーん。# apps/openssl engine pkcs11 -t WARNING: can't open config file: /usr/local/bind99/ssl/openssl.cnf (pkcs11) PKCS #11 engine support (sign only)# make install_ 上で作った openssl を使うようにして BIND をコンパイル。
FreeBSD では bin/pkcs11/Makefile の LIBS=-ldl の行をコメントアウトしないと途中でコケる。DIG_SIGCHASE はいいかげんデフォルトにしてほしい。% cd ../bind-9.9.0 % env CFLAGS=-DDIG_SIGCHASE=1 ./configure --prefix=/usr/local/bind99 --with-openssl=/usr/local/bind99 --with-pkcs11=/usr/local/lib/libsofthsm.so --enable-threads % make_ HSM 内に鍵を作って、それを bind が扱える形式として取り出す。取り出すといっても、ほんとに秘密の情報は HSM に入ったまま外に出てくることはない。
dnssec-keyfromlabel でも pkcs11-keygen で作るときに指定したラベルでちゃんと動いてくれた。きのうみたいに id をこねくりまわさなくて済む。逆に、スロット番号を指定できないので、HSM の slot 0 以外に鍵を作った場合にどうすればいいのかわからんのだが。# bin/pkcs11/pkcs11-keygen -l ksk -b 2048 Enter Pin: # bin/dnssec/dnssec-keyfromlabel -l ksk -f KSK example.com Enter PIN: Kexample.com.+005+31876 # bin/pkcs11/pkcs11-keygen -l zsk -b 1024 Enter Pin: # bin/dnssec/dnssec-keyfromlabel -l zsk example.com Enter PIN: Kexample.com.+005+52818_ この鍵で署名してみる。
やっと動いたよ。長かったな。# bin/dnssec/dnssec-signzone -S -K. -o example.com example.com Enter PIN: Fetching KSK 31876/RSASHA1 from key repository. Fetching ZSK 52818/RSASHA1 from key repository. Verifying the zone using the following algorithms: RSASHA1. Zone signing complete: Algorithm: RSASHA1: KSKs: 1 active, 0 stand-by, 0 revoked ZSKs: 1 active, 0 stand-by, 0 revoked example.com.signed_ ここまででとりあえず用は足りるのだが、鍵が必要になるたびに毎回 PIN を聞かれて手で入力する必要があるので自動化には向かない。ということで、これを省略できるようにする。全自動ゾーン署名(auto-dnssec) をやる場合や、cron で定期署名させる場合はこれをやっておく必要がある。
とーぜん、このファイルを見られると鍵が盗まれるのでそのぶんセキュリティレベルは落ちる。また、これをやっても、PIN 入力が不要になるのは dnssec-* なツールだけで、pkcs11-* なツールは手入力を求められる。こっちはコマンドライン引数で PIN を指定できるのでこれも自動化できないことはないんだが、どっちかに統一してほしいものだ。# vi /usr/local/bind99/ssl/openssl.cnf openssl_conf = openssl_def [ openssl_def ] engines = engine_section [ engine_section ] pkcs11 = pkcs11_section [ pkcs11_section ] PIN = hogehoge_ ちなみにふつーにコンパイルした BIND に LD_LIBRARY_PATH や LD_PRELOAD を使ってパッチを当てた openssl をかぶせてみてもできるんじゃないかと試してみたけどダメだった。理由は追ってないのでわからん。
_ ちうことで、鍵管理に HSM を使って (でも OpenDNSSEC は使わずに) DNSSEC する話でした。SoftHSM じゃなくてちゃんとしたハードウェアの HSM を使う場合もほぼ同様の手順でできるはず。
_ トラックパッドが押し込まれたまま戻らなくなった(泣)。常時クリック/ドラッグされてる状態でまともに操作できん。
_ 2009年11月に買った MacBook Pro。もう2年半か。もう十分元は取った気がするけど、今のところとくに不満もないんだよなぁ。修理に出すか買い替えるか。外に持ち出すことはあんまりないのでクラムシェルモードで使うという手もあるにはあるけど、美しくないなぁ。MacBook Air もあるけど、こいつはディスク容量その他いろいろ足りないのでこれ1台で済ませるわけにはいかないし。外付けマウスをつないで内蔵トラックパッドを無効にできればそれでいいんだろうけど、環境設定のメニューを見てもそんな項目はなさげ。マウスをつなぐと新しい設定項目があらわれるとかかしらん。
_ これまで、Windows のノート PC は買い替えた後で自宅サーバになるのが習わしだったんだけど、 amazon でノート PC がクソ安かったので次期自宅サーバ用に買ってしまったばかりなんだよ。きのう届いて Mac が今日壊れるとかタイミング悪すぎるだろ。常識的には、じゃあこいつを代わりに使うか、ということになるんだろうけど、こいつはキーボードが史上最悪レベルで使えないので常用する気にはまったくなれない。テンキーがついてるおかげでメインキーが左側に寄ってるし、何より enter がキーボードの右端中段にないので、手元を見ながらでないとまともに入力できない(注: テンキーつきキーボードは他人の PC を一時的にさわる以外では PC98 以来という人の感想です)。テンキーをつけるならせめてメインキーと間隔を十分に開けてくれ。買うときはサーバとして使う以外のことはまったく考えてなかったからそれでもよかったんだけれど。
_ DNSSEC 用に pkcs11 対応でビルドした openssl だけど、せっかくなんで別の用途でも使ってみる。
_ 秘密鍵を SoftHSM の中に作る。SoftHSM 自身に鍵作成用ツールがない(別で作ったものをインポート/エクスポートはできる)ので BIND で遊んだときのもので。
この鍵を利用して自己署名な SSL 証明書を作成。# pkcs11-keygen -b 2048 -l hogehoge Enter Pin: # pkcs11-list -l hogehoge label hogehoge Enter Pin: object[0]: handle 24 class 2 label[8] 'hogehoge' id[0] object[1]: handle 23 class 3 label[8] 'hogehoge' id[0]この証明書で SSL なサーバを起動。てっとりばやく openssl 自身をサーバに。# /usr/local/bind99/bin/openssl req -new -engine pkcs11 -keyform engine -key pkcs11:hogehoge -out hoge.pem -text -x509 engine "pkcs11" set. Enter PIN: (略) Country Name (2 letter code) [AU]: State or Province Name (full name) [Some-State]: Locality Name (eg, city) []: Organization Name (eg, company) [Internet Widgits Pty Ltd]: Organizational Unit Name (eg, section) []: Common Name (e.g. server FQDN or YOUR name) []:example.com Email Address []:パラメータをとくに指定してないのでデフォルトの *:4433 で listen してる。この s_server に接続してみる。# /usr/local/bind99/bin/openssl s_server -cert hoge.pem -engine pkcs11 -keyform engine -key pkcs11:hogehoge engine "pkcs11" set. Enter PIN: Using default temp DH parameters Using default temp ECDH parameters ACCEPTということで、example.com な自己署名なサーバに SSL でつながった。% openssl s_client -connect localhost:4433 CONNECTED(00000003) depth=0 /C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=example.com verify error:num=18:self signed certificate verify return:1 depth=0 /C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=example.com verify return:1 --- Certificate chain 0 s:/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=example.com i:/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=example.com --- Server certificate -----BEGIN CERTIFICATE----- (略) -----END CERTIFICATE----- subject=/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=example.com issuer=/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=example.com --- No client certificate CA names sent --- SSL handshake has read 1473 bytes and written 270 bytes --- New, TLSv1/SSLv3, Cipher is DHE-RSA-AES256-SHA Server public key is 2048 bit Compression: NONE Expansion: NONE SSL-Session: Protocol : TLSv1 Cipher : DHE-RSA-AES256-SHA Session-ID: 7B290D455029C51A0011022335AB3252A97B1A76E014F22F7C5552DFC664BC1B Session-ID-ctx: Master-Key: B229C8F269FA27FC79A67919472195E251DF3691DA092616BEA5CE1F8A06AD55D8BA5F00AAF69B6B3B03256BEA37CE10 Key-Arg : None Start Time: 1334629113 Timeout : 300 (sec) Verify return code: 18 (self signed certificate)_ ふつーの SSL と違いがわかりにくいんだけど、何が違うかというと SSL の秘密鍵がファイルではなくセキュリティデバイスの中に入ってるということ。鍵を盗むが困難になるのでセキュリティレベルが上がる。
_ Apache でやる場合は
って設定すればいいのかしら。んー、でもドキュメントを読むかぎり、SSLCryptoDevice は SSL アクセラレータとして使うためのものであって、秘密鍵の保管場所として使うことは意図してなさげな感じがする。SoftHSM がアクセラレータとして使えるかどうかは知らんが、仮に使えたとして遅くなることはあっても速くなることはありえない。SSLCertificateKeyFile にファイル以外のものを指定できるかどうかも怪しいし。試してないけど、もしこれで動いてしまったらラッキー、てな程度かな。postfix はドキュメントを見ても外部エンジンを使う設定項目がなさげなのでたぶん使えないと思う。SSLCryptoDevice pkcs11 SSLCertificateKeyFile pkcs11:hogehoge
_ 今回リリースされたのは 2.4.2だけだけど、LD_LIBRARY_PATH にカレントディレクトリが含まれてしまうという
静寂性脆弱性は 2.2 にも存在してる。それにしても起動スクリプトの脆弱性とはずいぶん珍しい。しかもわし的にかなり懐しいバグだ。_ ずっと前、今の会社に移る前の会社での仕事で、外注してたスクリプトを見たら先頭がこんな感じになってた。
単に変数に値をつっこんでるだけに見えるけど、実はこれ、セキュリティホールが存在する。外注先にすぐ直させた。#!/bin/sh PATH1=/bin:/usr/bin PATH2=/sbin:/usr/sbin PATH3=/opt/hoge/bin PATH4= PATH5= PATH=$PATH1:$PATH2:$PATH3:$PATH4:$PATH5:$PATH6:$PATH7:$PATH8:$PATH9_ 上のスクリプトは : を区切りとして空文字列を連結してしまって、最終的に PATH=/bin:/usr/bin:/sbin:/usr/sbin:/opt/hoge/bin:::::: になる。で、man sh してみるとこう書いてある。これは FreeBSD の ash の man だけど、それ以外の sh でも同様のことが書いてあるはず。
最後の行が重要。「$PATH で空ディレクトリはカレントディレクトリとみなす」。つまり、上の PATH 設定の状態でPath Search When locating a command, the shell first looks to see if it has a shell function by that name. Then it looks for a built-in command by that name. If a built-in command is not found, one of two things happen: 1. Command names containing a slash are simply executed without per- forming any searches. 2. The shell searches each entry in the PATH environment variable in turn for the command. The value of the PATH variable should be a series of entries separated by colons. Each entry consists of a directory name. The current directory may be indicated implicitly by an empty directory name, or explicitly by a single period.なんてのを /tmp/sl とかの名前で置いておくと、/tmp にいるときに ls と間違えて sl を実行したときに rm -rf / が実行されてシステムが破壊されてしまう。PATH にカレントディレクトリを入れてはいけないし、カレントディレクトリと同義である空文字列も入れてはいけない。個人的には空文字列をカレントディレクトリとみなすのは仕様バグだと思ってる。#!/bin/sh rm -rf /_ で、今日初めて知ったんだけど、PATH だけでなくて LD_LIBRARY_PATH も同様に空文字列をカレントディレクトリとみなす仕様だったのね。man ld.so しても書いてないみたいだけど。今回の apache の脆弱性はまさにこれ。起動スクリプトで LD_LIBARARY_PATH="/usr/local/apache/lib:$LD_LIBARARY_PATH" としてしまってるので、LD_LIBRARY_PATH が元々設定されていない場合は LD_LIBARARY_PATH に新たに空ディレクトリ(=カレントディレクトリ)を追加してしまって意図せぬライブラリをリンクしてしまう危険を抱えこんでいる。ちなみに関係ないが MANPATH はそういう動作はしないみたいだった。
_ 修正版はまだ出てないけど同じバグは 2.2.x にもあって、かつ起動スクリプトの修正だけで再コンパイル不要なんで、修正版を待たずにとっとと入れ替えておくとべきかと。対象は apachectl から読まれる envvars というファイル。ふつーにインストールした場合は apachectl と同じディレクトリにあるはず。このファイルの
になってるところをLD_LIBARARY_PATH="/path/to/apache/lib/:$LD_LIBARARY_PATH"に直せばおしまい。ちなみにこの envvars というファイルは設定ファイルの一種という扱いなので、既存の apache が存在してるところに新しいバージョンを上書きインストールしても、古いバージョンのものが優先されて更新されない。つまり、 上書き再インストールではこの脆弱性は修正できない。必ず手で書き換える必要がある。修正版リリースを待たなくていいというのはこれが理由。まあ、リモートから攻撃できる穴ではないので環境によってはそれほど急ぐ必要もないかもしれんが。if test "x$LD_LIBRARY_PATH" != "x" ; then LD_LIBRARY_PATH="/path/to/apache/lib:$LD_LIBRARY_PATH" else LD_LIBRARY_PATH="/path/to/apache/lib" fi_ なお、redhat や centos では envvars がやってる環境変数の設定のようなお仕事は /etc/sysconfig/ 以下のファイルでおこなうのが流儀なので、RPM では envvars なんてものはそもそも使わないようにパッチが当たっている。なのでこの穴は存在せず、修正も不要。
_ ネトゲ視点からの v6 fallback 問題の記事→ 格ゲーもFPSもカックカクになっちゃうの?
_ …えーと。サーバ側が v4 のみならまったく関係ないですよ?
_ 素朴な疑問なんですが、今度の World IPv6 Launch から v6 化する予定、あるいはそれを待たずにすでに v6 化しているゲーム屋さんってあるんでしょうか? あったら教えてほしい。そんなのあるわけねーだろ、という反語ではなく、純粋な疑問。もし対応したところがあるのならば話を聞いてみたい。
_ ところで、ネトゲやらんから知らんのですが、こういうのって L4 は TCP なんでしょうか UDP なんでしょうか。v6 → v4 へのフォールバックを短縮するための NTT 側の処理(TCP RST)はその文字からもわかるように TCP にしか効かないので、もし UDP だとすると v6 化されるとフレッツ網からは「初回の接続」がかなり待たされるだろうなー、と。ICMPv6 で dst unreach を返してはくれないのかしら。
_ あくまで、初回の接続だけ。まともな実装ならばサーバに接続に行くたびに v6 → v4 へのフォールバックをするとは思えんので、初回の接続で v6 がダメと判断されれば以後は v4 でのみ通信するでしょう。なので、ゲーム開始直後の最初の接続は時間がかかったとしても、その後のゲーム進行に問題は起きない、つまりカックカクにはならないんじゃないかと。タコな実装ならば毎回フォールバックすることもありえなくもないけど、ディレイを気にするようなネトゲならそのへんはちゃんとしてるんじゃないかな。これは TCP も UDP も同じ。
_ ゲーム屋さんが W6L を契機に v6 化しないとしても、いつまでも v4 のみってわけにもいかないだろうから、いずれこの問題に直面することになるのは避けられない。でもゲームなんて特定のクライアントプログラムから特定のホストにしか接続しないわけで、組み合わせなんてたかがしれてる。ぶっちゃけ、起動時に v4 と v6 で接続テストして回線品質のよさそうな方を使うように実装するだけだよね。対応はほかのアプリケーションよりもずっと楽そうに思える。
_ ゲーム業界のことはほとんど知らんので的はずれなことを書いてたらごめんなさい。