macのPHPからcURLでhttpsアクセスすると失敗する件
3時間ほどハマったのでメモ。 PHPのcURLからとあるサイトを読み込もうと思っても何故かcurl_exec()からはfalseが帰ってきます。当然全然関係のないサイトを指定すれば問題なく読み込めるのですが…。
curl_error()などを使ってエラー理由を調べた所、以下のようになりました。
Error Number:56 Error String:SSLRead() return error -9806
SSL関係でエラーとなっているようです。確かに読み込もうとしているページはhttpsのページでした。試しに他のhttpsサイトを試しましたがそちらは成功。特定のサーバー相手の場合のみ発生するようです。
いろいろ調べた所、どうもmacのhomebrewでインストールしたPHPはSSL通信のライブラリとして「Apple's Secure Transport」とかいうものをリンクするようなのですが、こいつがどうもTLSに対応していない?という事のようなのです。SSLv3は脆弱性が見つかっており無効にしてTLSを使うようにしているサーバーも多いので、そういったサーバーとは通信できずエラーとなるようです。
対症療法としては「Apple's Secure Transport」ではなく普通のOpenSSLライブラリを使うようにPHPを再インストールするという作業になります。私の環境の場合はphp5.6をインストールしている(参考)ので以下その場合の手順となります。
まずこの方法の対象はhomebrewでphpをインストールし、以下のコマンドを実行して所定の結果が出る場合となります。
$ php -i | grep "SSL Version" ↓ SSL Version => SecureTransport
一旦既にインストールしているphpをアンインストールします。
$ brew uninstall php56
homebrewのcurlをインストールします。
brew install --with-openssl curl
Apple's Secure Transportではなく、OpenSSLをリンクするように指定してphpをインストールします。
$ brew install \ --with-apache \ --with-homebrew-curl \ --with-homebrew-openssl \ --without-snmp \ --with-apxs2=/usr/sbin/apxs php56 $ brew install php56-mcrypt
これで再度コマンドを打って以下のようになれば成功です。
$ php -i | grep "SSL Version" ↓ SSL Version => OpenSSL/1.0.1j
apacheに反映させたい場合はapacheの再起動をお忘れなく。
これで無事にTLSのみ有効なサイトともhttps通信できました。
参考サイト
http://stackoverflow.com/questions/26461966/curl-post-to-https-url-returns-sslread-error