エックスサーバーがPHP8.4に対応、しかし・・・
先週、ついにエックスサーバーがPHP8.4に対応しました。
https://www.xserver.ne.jp/news_detail.php?view_id=16437
既にローカルのプロジェクトでは8.4を利用していたため、そのまま行けるだろう
→ 設定変更
→ 管理画面にログインできませんでした
え?なぜ?
エラーログ確認
エラーログを見ると、当プロジェクトは社内メンバー限定のため、社内で利用しているGoogle WorkspaceのドメインようにGoogleログイン、および外部利用ようにLINEログインで制限をかけているのだが、oAuth用のcurlコマンドでエラーが出ていた
cURL error 77: error setting certificate verify locations: CAfile: /opt/curl761/etc/pki/tls/certs/ca-bundle.crt
エラー調査
PHP8.3にダウングレードしてみると問題なく動作する。
つまりPHP8.4固有の問題
エラーが出ているcrtファイルを探してみる・・・ない
エラーの通り、/opt/curl761/etc/pki/tls/certs/ca-bundle.crt
なんてなかった。
そもそも /opt/curl761/etc
というディレクトリが存在しない。
ではPHP8.3はどこを見ているのか?
<?php
// 確認したいHTTPSのURL
$url = 'https://www.google.com';
// cURLのデバッグログを保存するためのストリームを用意
$verbose_log = fopen('php://temp', 'w+');
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// Verboseモードを有効にする
curl_setopt($ch, CURLOPT_VERBOSE, true);
// Verboseモードの出力先を$verbose_logに設定する
curl_setopt($ch, CURLOPT_STDERR, $verbose_log);
// cURL実行
$response = curl_exec($ch);
curl_close($ch);
// ストリームのポインタを最初に戻して内容を取得
rewind($verbose_log);
$verbose_output = stream_get_contents($verbose_log);
fclose($verbose_log);
// ブラウザで見やすいようにHTMLエスケープして表示
echo '<pre>' . htmlspecialchars($verbose_output) . '</pre>';
実行結果
* About to connect() to www.google.com port 443 (#0)
* Trying 142.250.76.132...
* Connected to www.google.com (142.250.76.132) port 443 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* CAfile: /etc/pki/tls/certs/ca-bundle.crt
CApath: none
以下省略
/etc/pki/tls/certs/ca-bundle.crt
を探すと確かに存在する
全然ちがうじゃん
存在するcrtを指定してみる ・・・ 成功
そりゃそうだ。
修正方法
1. 上記crtファイルを直接指定する
# curlコマンドの場合
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, '/etc/pki/tls/certs/ca-bundle.crt');
# League/oauth2-client を利用している場合
$provider->setHttpClient(new \GuzzleHttp\Client(['verify' => '/etc/pki/tls/certs/ca-bundle.crt']));
正直めんどい
2. php.ini に設定する(推奨)
- サーバーパネルにログイン
- php.ini設定
- 直接編集
- 以下を追記
[curl]
curl.cainfo = "/etc/pki/tls/certs/ca-bundle.crt"
これでいちいち設定しなくて良くなる。
なお /etc/pki/tls/certs/ca-bundle.crt
は /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem
へのシンボリックリンクなのでこちらを設定しても良い。
もっと突っ込んだ原因と考察
phpinfo で両バージョンを確認したところ、curl.cainfo
や openssl.cafile
はどちらも空(no value)だった。
つまり、大元となっている libcurlライブラリに設定が組み込まれているものと思われ、PHP8.4版のlibcurlの設定が間違っているのか、/opt/curl761/etc/pki/tls/certs/ca-bundle.crt
へのCAファイルの配置(ないしシンボリックリンクの作成)を忘れているのかどちらかだと思われる。
要するに、近々で修正される可能性もあるので、現状敢えてPHP8.4にする必要はないかもしれない。