Подключение к хосту https с помощью soapclient: как исправить проблемы SSL?

TL;DR

Я не могу подключиться к конечной точке https с помощью SoapClient. Поскольку мой wget возвращает a handshake failure, я подозреваю, что это причина.

Как я могу выполнить SOAP-запрос на этот сервер с помощью PHP?

полная

Я пытаюсь подключиться к SOAP-серверу (https). У него нет аутентификации сертификата клиента, поэтому соединение должно быть довольно простым, но, к сожалению, это не так.

Проблема в том, что я продолжаю получать сообщения Could not connect to host.

Метод подключения, который я использую, работает на другом сервере, и я подтвердил, что правильно настроил местоположение для этого сервера (изменил его на сервер, на который я управляю, и я получаю там ответ). Я подозреваю, что проблема связана с подключением https/ssl к серверу.

Ситуация

  • Я создаю PHP SoapClient на основе wsdl, который у меня локально.
  • Если я изменю конечную точку, я получаю заголовки запросов и ответов, и все работает как ожидалось.
  • машина доступна с моего сервера, хотя проблема возникает, когда я использую wget для подключения к ней (см. ниже)   Не удалось установить SSL-соединение.
  • Проблема также видна с помощью соединений openssl (см. ниже)

То, что я пробовал.

Есть много тем о "no connection!", но, очевидно, много "моего маршрутизатора было плохо, я сделал опечатку в адресе и т.д.". Я попробовал эти настройки, которые были предложены несколько раз, но больше как решение "cut'n'paste", чтобы быть уверенным, что это не сработало ", тогда из реальных рассуждений. Некоторые комментарии от меня добавили

Создание stream_context для параметров wsdl. Я пробовал

$context = stream_context_create(
              array(
                'ssl' => array(
                           'verify_peer' => false,  //default
                           'allow_self_signed' => true, //needs verify peer, tried that
                           'ciphers'=>"SHA1", // quite random.
                   ),
                'https' => array(
                           'curl_verify_ssl_peer'  => false,
                           'curl_verify_ssl_host'  => false
                          )
      )
            );
$options['stream_context'] = $context;

(сначала только опции ssl с verify_peer и allow_self_signed. Затем я добавил массив https, затем, наконец, я добавил ключ ciphers в ssl.)

Я нашел ссылку на эту ошибку, но 1) я не получаю это предупреждение, 2) кажется, это прокси- и 3) Моя версия больше не должна иметь ошибку. Я запускаю php 5.3.10

Когда я пытаюсь wget url, я получаю:

    wget https://[[servername]]/SOAP
    Resolving [[servername]] ([[servername]])... xxx.xxx.xxx.xxx
    Connecting to [[servername]]([[servername]])|xxx.xxx.xxx.xxx|:443... connected.
    OpenSSL: error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure

Если я попытаюсь соединиться с openssl, я получаю следующее:

$ openssl s_client -connect [[server]]:443 -state
CONNECTED(00000003)
SSL_connect:before/connect initialization
SSL_connect:unknown state
SSL3 alert read:fatal:handshake failure
SSL_connect:error in unknown state
3074463944:error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure:s23_clnt.c:724:

но если я заставляю ssl3, я получаю ожидаемый результат

$ openssl s_client -ssl3 -connect [[server]]:443 -state
CONNECTED(00000003)
SSL_connect:before/connect initialization
SSL_connect:SSLv3 write client hello A
SSL_connect:SSLv3 read server hello A
**happy certificate stuff. this is good**
Protocol  : SSLv3
Cipher    : DHE-RSA-AES256-SHA
**more happy certificate stuff. **

Я попытался добавить curl-wrapper из этого вопроса с установкой ssl_version в 3 (поскольку это, похоже, работает над командой openssl выше). Эта оболочка отбрасывает некоторые параметры, поэтому я не уверен, насколько это было бы полно. Кроме того, я все еще получаю ошибку рукопожатия, если я явно не установил проверку на false. Если я это сделаю (см. Ниже), я получаю пустой ответ.

curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, false);

Причины

Как было сказано выше, я подозреваю, что ssl рукопожатие, но я понятия не имею, как это исправить. Я не подозреваю о проблемах с wsdl или созданием клиента, поскольку соединение действительно работает с другим wsdl, тем же самым wsdl с другим набором местоположений и т.д. Это чисто эта (https) конечная точка, которая дает мне головные боли.

Дополнительные тесты.

Как и в предыдущем тесте с помощью обертки для скручивания, я попытался отправить минимальный конверт с мылом, который, по-видимому, предлагал @halfwarr в комментариях. Als возвращает пустой ответ.

Итак, с приведенным выше кажется, что у меня есть способ выжать http 204 из сервера, но это вряд ли удастся. Но это может быть второй проблемой? Не уверен.

Я предполагаю, что мне нужно попытаться заставить ssl3, но я понятия не имею, как (и это может быть неправильный путь, так что я пытаюсь не иметь проблема XY здесь:)

Ответ 1

Интересно. Попробуйте добавить это:

wget https://[[SERVER]]/soap/ —post-file=request.xml —header="Content-Type: text/xml" -O response.xml

Это сохранит результат как файл с именем response.xml.

Ответ 2

Последняя версия PHP 5.5.3 позволит вам установить версию SSL. Я видел других, которые могли использовать stream_context, но я тоже не смог получить эту работу.

Как работа и защита от сбоев, я использовал catch для захвата запроса о конверте мыла (аналогично тому, что вы тестировали выше):

$xml = $client->__getLastRequest()

и отправить через curl:


curl_setopt($ch, CURLOPT_SSLVERSION, 3);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

Это позволяет мне хотя бы двигаться вперед.