たけまるの日記

たけまるの日記です。web関係の技術ネタが多いですが、好きなことを適当に書いています。

macのPHPからcURLでhttpsアクセスすると失敗する件

3時間ほどハマったのでメモ。 PHPcURLからとあるサイトを読み込もうと思っても何故かcurl_exec()からはfalseが帰ってきます。当然全然関係のないサイトを指定すれば問題なく読み込めるのですが…。

curl_error()などを使ってエラー理由を調べた所、以下のようになりました。

Error Number:56
Error String:SSLRead() return error -9806

SSL関係でエラーとなっているようです。確かに読み込もうとしているページはhttpsのページでした。試しに他のhttpsサイトを試しましたがそちらは成功。特定のサーバー相手の場合のみ発生するようです。

いろいろ調べた所、どうもmacのhomebrewでインストールしたPHPSSL通信のライブラリとして「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