Curl POST to HTTPS url дает ошибку SSLRead()

Недавно я обновился до OSX 10.10. Yosemite и я с момента обновления не могу больше использовать Curl POST для SSL-url.

Сначала я использовал вызов wordpress wp_remote_request, а также попытался использовать curl в php. Оба (как и ожидалось) дают одно и то же сообщение об ошибке:

Номер ошибки: 56

Строка ошибки: ошибка возврата SSLRead() -9806

Примечание: когда я скручиваю POST на HTTP, он работает нормально. Я считаю, что это настройка в PHP.ini или в моем apache (после обновления я потерял свой оригинальный файл HTTPD.conf...).

Может ли кто-нибудь помочь мне?

Ответ 1

Я видел, что эта ошибка возникает, когда php скомпилирован с версией cURL, которая использует Apple Secure Transport под Yosemite и целью Запрос URL-адреса не поддерживает SSLv3 (который, вероятно, был отключен из-за уязвимости POODLE). Каков результат этой команды?

$ php -i | grep "SSL Version"

Я подозреваю, что вы увидите следующее:

SSL Version => SecureTransport

Вы можете преодолеть это, установив версию php, которая использует версию cURL, которая использует OpenSSL вместо SecureTransport. Это проще всего сделать с homebrew. Поэтому сначала установите это, если у вас его еще нет. Если homebrew установлен, но вы не запустили brew update с момента обновления до Yosemite, сделайте это первым. Также убедитесь, что вы установили XCode >= 6.1 и новейшие инструменты командной строки XCode. brew doctor расскажет вам, сделали ли вы все правильно.

Добавьте метки Homebrew ниже, которые вам понадобятся, чтобы установить пивоваренный php. Пропустите этот шаг, если эти репозитории уже прослушиваются. Если вы не уверены, что эти репозитории уже используются, просто запустите приведенные ниже команды. В худшем случае вы получите безобидный Warning: Already tapped!

$ brew tap homebrew/dupes
$ brew tap homebrew/versions
$ brew tap homebrew/php

Затем установите curl с помощью openssl:

$ brew install --with-openssl curl

Затем установите php, используя завиток, который вы только что установили, и заварили openssl:

$ brew install --with-homebrew-curl --with-httpd24 php55
  • если вы используете apache, обязательно добавьте LoadModule php5_module /usr/local/opt/php55/libexec/apache2/libphp5.so к вашему /etc/apache2/httpd.conf и перезапустите apache.

  • Если не использовать apache 2.4, вы можете удалить --with-httpd24 из приведенной выше команды.

  • если вы используете nginx, следуйте инструкциям caveat для начала fpm:

    Запуск php-fpm при запуске:

    mkdir -p ~/Library/LaunchAgents
    cp /usr/local/opt/php55/homebrew.mxcl.php55.plist ~/Library/LaunchAgents/
    launchctl load -w ~/Library/LaunchAgents/homebrew.mxcl.php55.plist
    

Установите любые расширения php, которые вам понадобятся, например. mcrypt.

$ brew install php55-mcrypt

После того, как вы закончите, запустите это снова:

$ php -i | grep "SSL Version"

И вы должны увидеть:

SSL Version => OpenSSL/1.0.2h

И теперь повторите проверку своего приложения, а SSLRead() return error -9806 должно исчезнуть.

Ответ 2

Эта ошибка SSL (код OSStatus: 9806) означает, что ваше соединение завершается сервером из-за ошибки при установлении соединения (например, при некорректной команде). Это происходит только в случаях, когда соединение SSL с удаленным хостом находится между ними.

Это плохо документировано руководством SSL (SSL_get_error), однако это сообщение об ошибке приходит из libcurl, построенного, которое используется с помощью защищенного сервера SecureTransport/Darwinssl TLS (вы можете найти его заголовок OSStatus в SecureTransport.h):

errSSLClosedAbort           = -9806,    /* connection closed via error */

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

Итак, убедитесь, что вы подключены к правильной сети (через WiFi), а другой HTTPS работает правильно. Если нет, проверьте, нужно ли указывать учетные данные прокси-сервера, или ваш интернет-провайдер переопределяет цепочку сертификатов и требует какой-либо проверки подлинности или в основном блокирует доступ к определенным сайтам в своем брандмауэре.

Ответ 3

У меня была аналогичная проблема с ошибкой SSLRead() return error -9806, а также я имел SSL Version => SecureTransport.

Но в моем случае проблема заключалась в том, что я устанавливал параметр curl CURLOPT_HTTP_VERSION:

$curl = curl_init();    
curl_setopt($curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);

Если вы удалите этот параметр, cURL определит, какую версию использовать по умолчанию. Подробнее см. curl_setopt для документации.

Это сработало для меня, и мне не нужно ничего менять с помощью cURL или PHP. Но это решение одного из многих случаев, когда появляется error -9806.