Как заставить 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, но в моем конкретном случае это не сработало.