1

I have a PHP client that needs to connect to a SOAP server:

$client = new \SoapClient('url_to_wsdl.wsdl', [
                'local_cert' => 'path_to_certificate.pem', 
                'connection_timeout ' => 300,
                'trace' => 1,
            ]);

$params = [];
$response = $client->executeAFunction($params);

But the SOAP client can't connect to the host: SoapFault "Could not connect to host" (it actually can't load the wsdl file either, but I mocked that by using a local copy of the file).

I came to the point where I figured out the Soap client cannot connect to the host because it seemingly uses IPv6 by default (I got to this point because of this answer on SO).

What have I done so far:

  • I already disabled IPv6 on my server (ubuntu), but that didn't change anything to the SOAP client.
  • I double-checked the reachability of websites over both IPv4 and IPv6 via the servers terminal

    $ curl -6 http://v6.testmyipv6.com/
    curl: (6) Could not resolve host: v6.testmyipv6.com
    
    $ curl -4 http://v4.testmyipv6.com/
    <html>
    <head>
    <title>IPv6 Test and Dual-Stack Test For Network Connectivity</title>
    ...
    
    # the above commands are true for all urls I tested
    

My actual question is: how can I tell the Soap client to connect to the host using IPv4 instead of using IPv6?

Community
  • 1
  • 1
Hans Vn
  • 787
  • 1
  • 16
  • 32
  • Check the DNS records. If the server isn't reachable over IPv6 then there must not be any AAAA records. – Sander Steffann Dec 29 '16 at 20:50
  • @SanderSteffann there is no AAAA record, that is the problem... The system can reach the server but tries to look it up over IPv6 resulting in a 'could not connect to host' fault. – Hans Vn Dec 30 '16 at 09:28
  • Clients use IPv6 by default only if there is an IPv6 address known. If there is no IPv6 address then clients fall back to IPv4 unless you force a specific protocol in some other way (like you did with curl). You must be having a different problem. – Sander Steffann Dec 31 '16 at 07:25

2 Answers2

2

Rather than binding to a specific IPv4 IP address, you can also substitute the IP address with 0:

stream_context_create(['socket' => ['bindto' => '0:0']]);

A full example of forcing IPv4 for a SoapClient might be:

$opts = array(
    'http' => array(
        'user_agent' => 'Your/UserAgent'
    ),
    'socket' => ['bindto' => '0:0']
);
$context = stream_context_create($opts);

$soapClientOptions = array(
    'stream_context' => $context,
    'trace' => true,
);
$client = new SoapClient($wsdlUrl, $soapClientOptions);
Mark Hamstra
  • 692
  • 1
  • 4
  • 16
1

A SOAP request is a socket connection, so you can use socket_context options. Use stream_context_create() to bind your request to a specified IP.

stream_context_create(['socket' => ['bindto' => '123.123.123.123:0']]);

Set 0 for port number so PHP will set this automatically.

Edd
  • 683
  • 1
  • 11
  • 21