やったことだけ書く備忘録

PHPのcurlで"SSL Connection Error."のエラーがどうしても出る時の対策

久々にどっぷりはまってしまった && ほとんど情報がなくて困ったので、解決策を備忘録として残しておこうと思います。



PHPのcurlでSSLのページにリクエストを送るとどうしてもエラーになってしまう



今回ハマったのは上記です。とあるECの案件で決済モジュールへのリクエストが必要で(当然SSL通信下で)、どれだけ設定を変えてもエラー、エラー、エラー…。ググっても情報は見つからず、何が原因かも分からないまま途方に暮れていたのですが、ふとしたことから閃き、そして解決まで至りました。原因は、↓でした。






NSS/3.13.1.0というSSL Versionを使ってるのがマズイようでした。
私のローカルでは、OpenSSLを使うようになっているのに、何故か今回のサーバではNSSを使う設定に。
また、SSLに問題があるのかと思って、



curl_setopt($handle, CURLOPT_SSL_VERIFYPEER, FALSE);



みたいな設定しましたが、これでもダメでした。証明書へのパスを渡したりしてもやっぱりダメ。
そもそもリクエストが送信できてない感じなんです。
file_get_contents($uri);だとちゃんとレスポンスが帰るのに…。

ちなみにさくらのVPSでCentOS x86_64、httpd、PHP、mysqlすべてyumで入れたものです。特におかしな設定はしておらず。



NSSとはなんぞや




Mozillaのサイトに詳細がありますね。

NSS FAQ - MDN

引用しますと、





OpenSSL はサーバサイド SSL、TLS、および汎用暗号化機能ライブラリを実装するオープンソースプロジェクトですが、PKCS #11 をサポートしていません。OpenSSL は Eric A. Young と Tim J. Hudson によって開発された SSLeay ライブラリに基づいており、Apache サーバで幅広く使用されています。Apache スタイルのライセンスが付与されています。

NSS は PKCS #11 や S/MIME をはじめとして、サーバおよびクライアント両方のアプリケーションをサポートしています。できるだけ多くの用途を可能にするため、NSS は Mozilla Public License と GNU General Public License の両方でライセンスされています。MPL 条項下または GPL 条項下のどちらでライセンスするかを選択することができます。




とのことです。NSSはサーバサイドだけでなく、クライアントサイドのアプリケーションでもSSLをサポートするような感じでしょうかね。Chromeも使ってるそうです。

Google Chrome が NSS を使うようになったのでSSL/TLS CipherSuite一覧を更新 - 自堕落な技術者の日記

まぁ、それはともかくとして、PHPのcurlでNSSが使われている理由が分かりません・・・。
そして何故かNSSだと、以下の様なcurlのPOST/PUTリクエストのみ失敗するらしいです。

Delayed responses for cURL SSL PUTs/POSTs (php) (NSS vs OpenSSL)


さすがStack Overflowさん・・・。失敗、というよりはレスポンスに遅延が見られる、という内容でしたが、現象はよく似ていて、これがヒントになりました。

ここから解決まであーだこーだやったログなどを書きます。



PHPをソースコードからインストールしてみよう(curlは組み込みだしね)



まずはyumで入れたPHPを削除。




# yum -y remove php php-common
 


それから、DLとコンパイルします。選択したのはPHP5.3.14です。




# ./configure ... --with-curl --with-openssl ...
 


って感じで、curlの有効化とOpenSSL使うよーってオプションを渡してコンパイルしました。結果は↓







変わってません。見事にNSS。試しにリクエストしてみましたが、やっぱりダメ。



libcurl.soがおかしいんじゃないの?



libcurlはyumで入れてたんですが、「そもそもこれがおかしいんじゃない?」と気づき、libcurlをソースコードから入れてみる事にしました。cURLのサイトでは、7.26が最新版だったので、これをOpenSSLを有効にしてlibcurl.soを生成してみることにしました。




# wget http://curl.haxx.se/download/curl-7.26.0.tar.gz
# tar xvfz curl-7.26.0.tar.gz
# cd curl-7.26.0
# ./configure --prefix=/usr/local
# make
# make install
 


特にオプションを指定せずにコンパイルしましたが、OpenSSLを使う設定になっていました。で、できたsoをコピー。




# cp /usr/local/libcurl.so* /usr/lib64/
 


この状態で、再度PHPをコンパイルし、apacheを再起動した後にphpinfo()を見てみると・・・





OpenSSLになりました!!
そして試しにリクエストを送った所、エラーもなく正常にリクエストが成功しました。



と、いうわけで



原因はcurlがSSLにNSSを使っていたから、という原因特定に至りました。
とはいえ、なぜデフォルトの設定でNSSになっていたのか(他に立てたサーバはOpenSSLだったのに)、
そしてNSSだとなぜSSL通信先のPOSTリクエストに失敗するのか。

大事な部分は分からず終いだったわけですが、とりあえず通信ができて、レスポンスが帰ったので良しとします。。。



まとめ




パラメータが云々よりも、コンパイル条件をチェックした方がいい時もありますよ!!

ということですね。

« 前の記事 次の記事 »

5件のコメント

通りすがり さん

原因の切り分けにとても参考になりました。ありがとうございます!
結局、こちらの環境ではIPv6を無効にすればNSSでも名前解決が出来たのでそちらを採用しました。

sugimoto1981 さん

なるほどー、IPv6関連は失念しておりました。
NSSはまだIPv4でないといけないということですかね。
ありがとうございます!

小島丈幸 さん

要点がまとまっているよい記事ですね。助かりました。
当方はリポジトリを追加して yum で libcurl をインストールする方法でなんとかなりました。
が、今コメントしようとして、IPv6 切るだけでよかったんだ、と知った次第です。
ともかく、ありがとうございました。

通りすがり さん

一日中苦戦していてついにこちらにたどり着き、
記載されている方法で解決することができました。
ありがとうございました!

ijezocus さん

http://usa-onlineprednisone.net/ - usa-onlineprednisone.net.ankor <a href="http://salbutamol-ventolin-buy.net/">salbutamol-ventolin-buy.net.ankor</a> http://online-viagracanada.net/

コメントを投稿する

 画像に表示されている文字を入力してください。