Ruby の SSL の証明書検証の失敗でハマっていた

基本的な流れ

  1. TIG から tig.rb に移行しようと思い立った
  2. tig.rb が先日の DNS 障害の件を受けて SSL の証明書をちゃんと検証するようになった
  3. 自宅サーバの FreeBSD 上の Ruby で CA証明書が認識されておらず、結果 twitter.com のサーバ証明書を検証できずにコケていた。

tig.rb のアップデート - 冬通りに消え行く制服ガールは、夢物語にリアルを求めない。 - subtech

を読む前にハマってました><

だらだらと言い訳

  1. 本番と検証で3種類のRubyを使っていた
    • ports ( Ruby 1.8.7 ) on FreeBSD
    • MacPorts ( Ruby 1.8.7 ) on MacOSX
    • Fink ( Ruby 1.8.6 ) on MacOSX
  2. ports のものだけ証明書がインストールできてなかった
  3. たまたま ports のものだけ tiarra と組み合わせていたので tiarra にあらぬ疑い
    • ここでしばらくハマる
  4. 最終的には RFC と tig.rb の中身を読んで tiarra を除外、エラーメッセージを検索して Net::HTTP に矛先が

最初はバグを疑った。

14:25:09 >wtnabe< http://bit.ly/4tHhtN この patch 適用したら
OpenSSL::SSL::SSLError 例外に出会えた。

このパッチを当ててみた。すると OpenSSL 周りの例外が出てきたので、とにかく SSL の問題だということで落ち着く。tig.rb を読むと SSL の verify_mode をセットしている部分があったので試しにこれを外してみたら動いた。

Twitter / wtnabe: さっきのパッチ当てた状態で tig.rb を htt …

14:38:26 >wtnabe<さっきのパッチ当てた状態で tig.rb を
http://gist.github.com/276924 こうしたら動いた。ここまできて残りは証明
書か。とりあえず tiarra のせいでもなんでもなかった。

Twitter / wtnabe: net/http を元に戻しても動いた。ということで …

net/http を元に戻しても動いた。ということで openssl で使う証明書の問題
だった。もしくは tig.rb で証明書をまともにチェックしないようにしちゃう
か、どっちか。

この状態で Net::HTTP を元に戻してみたがやはり正常に動作した。ということは本当に単なる SSL の問題。

その後、

Twitter / : @wtnabe tig.rb動かしてるのがFreeB …

18:18:54 <otsune> @wtnabe tig.rb動かしてるのがFreeBSDだったので
security/ca_root_nssいれた

と @otsune に情報をいただいたので、security/ca_root_nss を入れたけど、うまく動かず。最終的にはインストールされていたパスの問題で、

Twitter / wtnabe: VERIFY_PEER でも /usr/local/ …

00:05:34 >wtnabe< VERIFY_PEER でも /usr/local/openssl/cert.pem@ ->
/usr/local/share/cert/ca-root-nss.crt の link で動いたっぽい。

ということで tig.rb を元に戻して link 張って解決。長かった!

結局、インストールしていた証明書を正しく認識していなかっただけ。でも Net::HTTP のエラーの出方も分かりにくいよねぇ?

ちなみに他にもハマっていた人が。

Twitter / Yugui (Yuki Sonoda): このRubyはどのOpenSSLとリンクされるんだー …

※ Ruby 1.9 の方は Ruby 1.9 - Feature #2579: Net::HTTP.start("www.ruby-lang.org", use_ssl: true) で SSL 利用を可能に - Ruby Issue Tracking System で証明書の検証をデフォルトで行うようになる新 API が入りました。

残り関連のログをコピペ。

2010-01-15:12:05:40 @yugui favられてたのでちょっとまとめる時間を端折っ
てお伝えしますと、RubyのNet::HTTP.new()はSSLの検証に失敗したときに
@socketがnilのままになるんだけど、考慮されてないパターンがあるという問
題でした。
http://groups.google.co.jp/group/linux.debian.bugs.dist/browse_thread/thread/27dae518c1c5d617
2010-01-15:12:19:11 @yugui SSLの検証失敗をどうやって知るのか、という意
味では.request()がnil.closed?()になってしまうとか、あるいはinspectした
ときのopen=falseだけだとちょっと分かりにくいかなとは思います。

More