httpsページに接続できない件(wget/curl/HTTP_Request)

つい先日出た現象について覚え書き。
例の脆弱性の件もあるしやっぱり今後は最新版で動かしたいよね。
って事でためしに以下のAmazonLinuxにてお仕事サイトを動かしてみる事に。

$ cat /etc/system-release
Amazon Linux AMI release 2014.03

$ openssl version
OpenSSL 1.0.1g-fips 7 Apr 2014

$ rpm -qa | grep openssl
openssl-1.0.1g-1.69.amzn1.x86_64

$ php -v
PHP 5.5.10 (cli) (built: Mar 27 2014 23:56:37) 
Copyright (c) 1997-2014 The PHP Group
Zend Engine v2.5.0, Copyright (c) 1998-2014 Zend Technologies

$ pear version
PEAR Version: 1.9.4
PHP Version: 5.5.10
Zend Engine Version: 2.5.0

ところが別系統システムへの接続で問題が...
内容としてはPEARのHTTP_RequestでAPIをコールというありがちな処理なんですが...
PHP上でAPIのレスポンス自体が取得できない。
(HTTP_Request2じゃない点がアレですがそこは色々な事情があってゴニョゴニョ)

問題を切り分けたいので既存システムとは別にphpファイル作って

require_once "PEAR.php";
require_once "HTTP/Request.php";
$http_request = new HTTP_Request("https://hoge/api");
$http_response = $http_request->sendRequest();
if (PEAR::isError($http_response)) {
  echo $http_response->getMessage();
} else {
  echo $http_request->getResponseBody();
}

動かして見たところ

fsockopen(): unable to connect to ssl://hoge/api:443 

HTTP_Requestに問題ありか?ってことでwgetで試す

$ wget https://hoge/api
--2014-04-18 15:17:25--  https://hoge/api
hoge をDNSに問いあわせています... xxx.xxx.xxx.xxx
hoge|xxx.xxx.xxx.xxx|:443 に接続しています... 接続しました。
OpenSSL: error:1407742E:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert protocol version
SSL による接続が確立できません。

うーむSSLの接続自体に問題があるっぽい。
英語で出てきた一部情報によるとプロトコルのネゴシエーションがどうたらこうたら。
試しにwgetのオプションに
--secure-protocol=TLSv1
をつけてみたら取得成功

ちなみに別のサイトのhttpsページをオプション無しでwgetしてみるとすんなり取得成功。
なんなんだ・・・
普段このあたりを意識する事などないのでなかなか厳しい。

curlでもためしてみるか。
SSLバージョン指定できるオプションがあるようなので

$ch = curl_init();
curl_setopt_array($ch,
  array(
    CURLOPT_URL=> "https://hoge/api",
    CURLOPT_SSLVERSION=>3,
  )
);
curl_exec($ch);
curl_close($ch);

こちらは取得成功。
※CURLOPT_SSLVERSION無しで動かしてみるとNG。

HTTP_RequestにはSSLバージョン指定的なオプションが無いようなので、試しに直接書き換え
/usr/share/pear/HTTP/Request.php
707行目あたりの

$host = 'ssl://' . $host;

$host = 'tls://' . $host;

に変えてみたら取得成功。
やっぱりこのへんか...

HTTP_Request2ではAdapterとしてcURLが指定できるそうなので、そっちに置き換えた上でSSLバージョン指定してしまうのが順当な感じか。
しかしモノがモノだけにさくっと置き換えて完了という訳にもいかず。
ちょっと古めのopensslなら問題無しなんだけどいつまでもそれではちょっと・・・
どうしたもんですかね。

参考サイトにあったようにPHP再コンパイルっていう手もある模様。
phpinfo見てみたらうちも見事にSSL VersionはNSS/3.15.3でした。

参考にさせていただいた事例
ニコニコ動画にhttps(SSL)接続できなかった件
PHPのcurlで"SSL Connection Error."のエラーがどうしても出る時の対策

追記
参考サイトのはてブコメントにて気になる情報。
相手方が古めのIISだとこうなるという。あ・・・
結局、該当箇所だけcurlに置き換えることでどうにかこうにか対応完了

更に追記(2014/10/16)
SSL3.0が無効になってて困ってる事例多数出ているようです


コメントを残す