Как заставить определенную версию TLS в контексте потока PHP для транспорта ssl: //?

Как заставить TLSv1.0 в контексте потока PHP при попытке получить доступ к URL-адресу https ?

Я ищу что-то вроде этого:

 $context = stream_context_create( array( 'ssl' => array( 'protocol_version' => 'tls1', ), )); file_get_contents('https://example.com/test', false, $context); 

Задний план

На самом деле я столкнулся с проблемой в Ubuntu 12.04 при работе с SoapClient PHP. К сожалению, сервер, к которому я пытаюсь подключиться, поддерживает только SSLv3.0 / TLSv1.0 и терпит неудачу при согласовании TLSv1.1 по умолчанию. Поэтому я хотел бы явно установить протокол транспорта ssl:// в TLSv1.0.

Пользователи PHP 5.6+

Это новая функция, описанная на странице изменений PHP 5.6 OpenSSL .

На момент написания этого, PHP5.6 находится в Бета1, и, следовательно, это не слишком полезно. Люди будущего – вам повезло!

Будущее на нас. PHP 5.6 – вещь, и ее использование следует поощрять. Имейте в виду, что он обесценивает некоторые довольно широко используемые вещи, такие как функции mysql_ *, поэтому следует проявлять осторожность при обновлении.

Все остальные

@toubsen верен в своем ответе – это невозможно. Чтобы подробно описать предлагаемые способы его решения … при работе над проблемой, когда сервер API поставщика неправильно согласовал TLSv1.2 до поддерживаемого TLSv1.0, отправка небольшого подмножества шифров, по-видимому, позволила правильному завершению согласования. Код контекста потока:

 $context = stream_context_create( [ 'ssl' => [ 'ciphers' => 'DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:AES256-SHA:KRB5-DES-CBC3-MD5:KRB5-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:EDH-DSS-DES-CBC3-SHA:DES-CBC3-SHA:DES-CBC3-MD5:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA:AES128-SHA:RC2-CBC-MD5:KRB5-RC4-MD5:KRB5-RC4-SHA:RC4-SHA:RC4-MD5:RC4-MD5:KRB5-DES-CBC-MD5:KRB5-DES-CBC-SHA:EDH-RSA-DES-CBC-SHA:EDH-DSS-DES-CBC-SHA:DES-CBC-SHA:DES-CBC-MD5:EXP-KRB5-RC2-CBC-MD5:EXP-KRB5-DES-CBC-MD5:EXP-KRB5-RC2-CBC-SHA:EXP-KRB5-DES-CBC-SHA:EXP-EDH-RSA-DES-CBC-SHA:EXP-EDH-DSS-DES-CBC-SHA:EXP-DES-CBC-SHA:EXP-RC2-CBC-MD5:EXP-RC2-CBC-MD5:EXP-KRB5-RC4-MD5:EXP-KRB5-RC4-SHA:EXP-RC4-MD5:EXP-RC4-MD5', ], ] ); 

Пользователи SOAP

PHP-клиент SOAP не использует завиток и не использует контекст по умолчанию, заданный с помощью stream_context_set_default . Таким образом, созданный контекст должен быть передан конструктору SOAPClient во втором параметре как таковой:

 $soap_client = new SOAPClient('http://webservices.site.com/wsdlfile.wsdl', array('stream_context' => $context)); 

Почему эти Шиферы?

Запуск команды openssl ciphers на сервере дает вам список поддерживаемых шифров в вышеуказанном формате. Запуск openssl ciphers -v сообщает вам те, которые имеют TLSv1.2. Вышеприведенный список был составлен из всех шифров, отличных от TLSv1.2, сообщенных OpenSSL.

openssl ciphers -v | grep -v 'TLSv1.2' | cut -d ' ' -f 1 | tr "\n" ':'

Основная информация

Поле protocol_version действует только для HTTP-контекста (HTTP 1.0 vs 1.1), но не влияет на контекст SSL.

На следующей странице руководства перечислены все параметры контекста потока для PHP: параметры и параметры контекста

Для всех оберток потоков на основе SSL доступны только следующие параметры: параметры контекста SSL

Возможные решения / обходные пути

Первый совет: попросите администратора сервера исправить свой сервер, а не работать вокруг этого в вашем клиенте 😉

Возможно, вы можете получить это с помощью функции ciphers для потоков SSL, чтобы передать только один точный набор шифрования TLSv1.0 (уникальный для TLSv1.0) в списке, который поддерживает ваш целевой сервер.

Переключение реализации на использование cURL, скорее всего, также не поможет здесь, так как согласно записи в своем списке рассылки нет возможности принудительно установить определенную версию TLS – клиент будет автоматически понижаться по мере необходимости.

ТЛ; др

В настоящее время я не знаю, как явно принудительно заставить TLSv1.0 для SSL-соединений с PHP.

Если кто-то хочет знать, как «отключить» TLSv1.0 при выполнении запроса SOAP …

 $parameters = array( 'trace' => true, 'exceptions' => true, 'cache_wsdl' => WSDL_CACHE_NONE, 'stream_context' => stream_context_create(array( 'ssl' => array( 'ciphers' => 'DEFAULT:!TLSv1.0:!SSLv3' ), )), 'connection_timeout' => 15 ); $client = new SoapClient(YOUR_WSDL_URL_HERE, $parameters); 

Ключевая роль здесь заключается в том, что потоковая контекстная шифровальная линия. В нем говорится, что используются шифры по умолчанию, но исключают шифры TLSv1.0 (в пакете 1.0 также есть шифры TLSv1.1). Это: разделитель пакетов шифрования (что происходит между пакетами) и! здесь нужно сказать, чтобы исключить этот пакет (это жесткое исключение, поэтому, если оно появится позже в списке, оно все равно будет исключено). Мягкое исключение – символ и добавление в конец списка + символ. Чтобы добавить, просто добавьте его без чего-либо перед ним.

Шифрование информации здесь: https://www.openssl.org/docs/manmaster/man1/ciphers.html#CIPHER-LIST-FORMAT

Изменить: по любой причине, включая

 'ssl_method' => SOAP_SSL_METHOD_TLS, 

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

Я могу подтвердить, что выше принятый ответ не работает для комбинации Ubuntu 12.04 и PHP 5.4.33. Также выяснилось, что я должен вручную указать сертификат при попытке openssl и завивать для доступа к конечным точкам https. Я закончил использование RHEL 7 и PHP 5.5 для достижения прочного решения, поскольку я разрабатывал интеграцию для корпоративного приложения. Ничего против Ubuntu, но в моем конкретном случае это не сработало.