web-dev-qa-db-ja.com

なぜRuby= SSL証明書を検証できないのですか?

XMLRPC :: Clientライブラリを使用してリモートAPIと対話しようとするのはこれが初めてであり、このエラーが引き続き発生します。

warning: peer certificate won't be verified in this SSL session

あちこち検索して、そのエラーを受け取った人をたくさん見つけました。通常、それは自己署名証明書であり、彼らはただそれを消したいので、彼らはXMLRPC :: Clientがhttpセッションを開いているようにモンキーパッチのような汚いことをします。

証明書が有効かどうかを気にしないクライアントだと最初に思っていたので、検索を続けて this gem に出会いました。単にすべてのSSL証明書の検証を強制し、それもできない場合はハードエラーをスローします。これはまさに私が望んでいたものでした。私はそれを含め、再びコードを実行しましたが、今はこれを取得しています:

OpenSSL:SSL::SSLError:
  SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B:
  certificate verify failed

もちろん!証明書が悪い!しかし、opensslの組み込みs_clientで次のように確認するために、二重チェックを行います。

openssl s_client -connect sub.example.com:443

そして私は何を得るのですか:

CONNECTED(00000003)
---
Certificate chain
<snip>
Verify return code: 0 (ok)

それでは、私の質問に行きましょう。 OpenSSL(コマンドラインバージョン)は、証明書が良好であると言います。 OpenSSL(Rubyライブラリ)は同意しません。私のすべてのWebブラウザーは、証明書が良いと言っています。

役に立つかもしれないいくつかの追加の詳細。証明書はワイルドカードですが、ドメインに対して有効です。 openssl s_clientは、Rubyコードとは別の同じマシンで実行されました。これは、RVMと共にインストールされるRuby 1.8.7 p357です。

Rubyは、ホストOSによって提供されるCAバンドル以外のものを使用しますか? Rubyに特定のCAバンドルまたはシステムバンドルを使用するように指示する方法はありますか?

53
Sam Stelfox

Ruby OpenSSL s_clientと同じように動作する方法、またはブラウザの動作方法にのみ興味がある場合は、最後のセクションにスキップして、罰金をカバーします。以下の内容を印刷します。

デフォルトでは、接続に使用されるOpenSSL::X509::Storeは、信頼できる証明書をまったく使用しません。アプリケーションドメインの知識に基づいて、通常、X509::Storeのインスタンスに、アプリケーションに関連する信頼できる証明書をフィードします。これにはいくつかのオプションがあります。

  • Store#add_fileは、PEM/DERでエンコードされた証明書へのパスを取ります
  • Store#add_certはX509 :: Certificateのインスタンスを取ります
  • Store#add_pathは、信頼できる証明書が見つかるディレクトリへのパスを取ります

「ブラウザ」アプローチ

これは、ブラウザ、Java(cacerts)、または信頼できる証明書の独自の内部ストアを持つWindowsが取る方法とは対照的です。ソフトウェアには、一般にこれは悪い考えではありませんが、実際にこれらのセットを調べると、証明書が多すぎることにすぐ気付くでしょう。これらの証明書のallが盲目的に信頼されるべきかどうかを本当に教えてください。

Rubyアプローチ

典型的なRubyアプリケーションの要件は、ブラウザの要件とは大きく異なります。ブラウザは、付属の「正当な」Webサイトにナビゲートできる必要があります。 TLS証明書であり、httpsを介して提供されます。しかし、通常のRubyアプリケーションでは、TLSを使用するか、証明書の検証が必要ないくつかのサービスのみを処理する必要があります。

また、Rubyアプローチ-さらなる手作業が必要ですが、特定のアプリケーションコンテキストで信頼する必要がある証明書を正確に信頼する、手作業のソリューションになります。これは面倒ですが、攻撃対象がはるかに少ないため、この方法でセキュリティが大幅に向上します。最近のイベントを考えてみましょう。DigiNotarまたは他の侵害されたルートを信頼セットに含める必要がない場合。

ただし、既にお気付きのように、デフォルトでは、信頼できる証明書を積極的に追加しないと、OpenSSL拡張機能はanyピア証明書。動作させるには、構成を手動でセットアップする必要があります。

この不便さは、それを回避するための多くの疑わしい手段につながりました。最悪なのは、グローバルにOpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONEを設定することです。これをしないでください。ハッキングに遭遇した場合にアプリケーションがランダムにクラッシュするコードを追加することについて冗談を言っています:)

手動の信頼設定が複雑すぎると思われる場合は、OpenSSL拡張がs_clientなどのOpenSSL CLIコマンドとまったく同じように動作する簡単な代替手段を提供します。

S_clientが証明書を検証できる理由

OpenSSLは、ブラウザーとWindowsに対して同様のアプローチを使用します。通常のインストールでは、信頼できる証明書のバンドルがハードディスクのどこかに(/etc/ssl/certs/ca-bundle.crtのようなもの)置かれ、これが信頼できる証明書のデフォルトセットとして機能します。 s_clientがピア証明書を検証する必要があるときに見える場所であり、それがあなたの実験が成功した理由です。

Ruby s_clientのように振る舞う

Rubyで証明書を検証する際に同じ快適さを維持したい場合は、OpenSSL::X509::Store#set_default_pathsを呼び出すことで、システム上で信頼できる証明書のOpenSSLバンドルを使用できるように指示できます。追加情報は here にあります。 XMLRPC::Clientでこれを使用するには、使用するset_default_pathsX509::Storeが呼び出されるようにするだけです。

113
emboss

CA証明書ファイルがある場合は、次のようにします。

http.ca_file = <YOUR CA-CERT FILE PATH>
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
http.verify_depth = 5
0
Guihen