PHP cURL не работает с HTTPS

У меня были проблемы на моем сервере разработки, где cURL, отлично работая с чем-либо HTTP, не работает должным образом с чем-либо HTTPS - даже с тем же самым ресурсом с различными протоколами (для тестирования я запрашивал google.com используя как http, так и https).

Полученная ошибка cURL равна 35: "Проблема возникла где-то в рукопожатии SSL/TLS".

Я расчесывал web и SO для решений, и все они были либо для установки CURLOPT_SSL_VERIFYPEER на false, что ничего не меняет, либо загружает файл сертификата и устанавливает CURLOPT_CAINFO на свой путь, что также ничего не меняет.

При настройке сертификата я выполнил инструкции этот учебник и этот учебник, пытаясь как загрузить сертификат для запрашиваемого ресурса, так и загрузить пакет сертификатов.

Я также попытался явно установить CURLOP_PORT на 443. Для тщательности моего вопроса, другие параметры, которые я установил, это CURLOPT_VERBOSE = true, CURLOPT_RETURNTRANSFER = true и CURLOPT_SSL_VERIFYHOST = 2 (я пробовал каждую комбинацию из 1 и 2 с VERIFYPEER - true и false). Я также убедился в phpinfo(), что у меня есть OpenSSL, и он включен.

Я использую много старого кода, который отлично работал на моем последнем производственном сервере, поэтому этот код работал раньше. Но этот хостинг был общим хостингом, и я не знаю большую часть конфигурации там.

Ответ 1

Curl не имеет встроенных корневых сертификатов (как это делает большинство современных браузеров). Вам нужно явно указать его на файл cacert.pem:

  curl_setopt($ch, CURLOPT_CAINFO, '/path/to/cert/file/cacert.pem');

Без этого curl не может проверить сертификат, отправленный обратно через ssl. Этот же файл корневого сертификата может использоваться каждый раз, когда вы используете SSL в curl.

Вы можете получить файл cacert.pem здесь: http://curl.haxx.se/docs/caextract.html

Ответ 2

Как насчет этого. Он выбирает то, что может быть домашней страницей HTTPS Google. (Поскольку я отключил проверку сертификата, у меня нет возможности узнать, что это настоящая домашняя страница Google.) Это должно помочь вам.

<?PHP

// connect via SSL, but don't check cert
$handle=curl_init('https://www.google.com');
curl_setopt($handle, CURLOPT_VERBOSE, true);
curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
curl_setopt($handle, CURLOPT_SSL_VERIFYPEER, false);
$content = curl_exec($handle);

echo $content; // show target page
?>

Ответ 3

Найти, если ваша ОС содержит каталог сертификатов. Если это так, то требуемые сертификаты CA часто уже будут включены. Например, в Ubuntu обычно /etc/ssl/certs. Если этот каталог существует, задайте параметр пути CA:

curl_setopt($ch, CURLOPT_CAPATH, '/etc/ssl/certs');

В качестве альтернативы вы можете ссылаться на один файл сертификата CA. Включите файл cacert.pem в свой проект или установите его на свой сервер. Загрузите из надежного источника, например. cacert.org. Для одного файла не устанавливайте CAPATH и вместо этого устанавливайте только CAINFO:

curl_setopt($ch, CURLOPT_CAINFO, '/path/to/cacert.pem');

Отключение проверки сверстников и хостов - это быстрое, но небезопасное обходное решение для реальной проблемы. Эти функции существуют по уважительной причине: поэтому вы можете доверять через стороннюю сторону, что система, к которой вы подключаетесь, является той, которую вы ожидаете.

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);