1

I have a strange behavior of cURL.

When I try to make a request using PHP functions, like this:

$curl = curl_init();

curl_setopt_array($curl, array(
    CURLOPT_URL => "https://<url_here>",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_SSL_VERIFYPEER => false,
    CURLOPT_SSL_VERIFYHOST => false,
    CURLOPT_POST => 1,
    CURLOPT_POSTFIELDS => "<body here>",
    CURLOPT_HTTPHEADER => array(
        "content-type: application/xml"
    ),
));

I get Failed to connect to <url_here> port 443: Connection refused.

But when I try to make exactly the same call from command line (on the server, where PHP script is located), I get a valid response. So, the environment is fine, nothing blocks the 443 port.

Moreover, when I run the same PHP code on another server, it also works.

Is it possible that some PHP configuration options prevents cURL from working? Or should I check something else?

Thanks.


Output of local curl_version():

array(9) {
  ["version_number"]=>
  int(470784)
  ["age"]=>
  int(3)
  ["features"]=>
  int(968605)
  ["ssl_version_number"]=>
  int(0)
  ["version"]=>
  string(6) "7.47.0"
  ["host"]=>
  string(19) "x86_64-pc-linux-gnu"
  ["ssl_version"]=>
  string(14) "OpenSSL/1.0.2g"
  ["libz_version"]=>
  string(5) "1.2.8"
  ["protocols"]=>
  array(21) {
    [0]=>
    string(4) "dict"
    [1]=>
    string(4) "file"
    [2]=>
    string(3) "ftp"
    [3]=>
    string(4) "ftps"
    [4]=>
    string(6) "gopher"
    [5]=>
    string(4) "http"
    [6]=>
    string(5) "https"
    [7]=>
    string(4) "imap"
    [8]=>
    string(5) "imaps"
    [9]=>
    string(4) "ldap"
    [10]=>
    string(5) "ldaps"
    [11]=>
    string(4) "pop3"
    [12]=>
    string(5) "pop3s"
    [13]=>
    string(4) "rtmp"
    [14]=>
    string(4) "rtsp"
    [15]=>
    string(3) "smb"
    [16]=>
    string(4) "smbs"
    [17]=>
    string(4) "smtp"
    [18]=>
    string(5) "smtps"
    [19]=>
    string(6) "telnet"
    [20]=>
    string(4) "tftp"
  }
}

Output of local curl -V:

curl 7.47.0 (x86_64-pc-linux-gnu) libcurl/7.47.0 GnuTLS/3.4.10 zlib/1.2.8 libidn/1.32 librtmp/2.3
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtmp rtsp smb smbs smtp smtps telnet tftp
Features: AsynchDNS IDN IPv6 Largefile GSS-API Kerberos SPNEGO NTLM NTLM_WB SSL libz TLS-SRP UnixSockets

Output of server's curl_version():

array(9) {
  ["version_number"]=>
  int(462597)
  ["age"]=>
  int(2)
  ["features"]=>
  int(1597)
  ["ssl_version_number"]=>
  int(0)
  ["version"]=>
  string(6) "7.15.5"
  ["host"]=>
  string(23) "x86_64-redhat-linux-gnu"
  ["ssl_version"]=>
  string(15) " OpenSSL/0.9.8b"
  ["libz_version"]=>
  string(5) "1.2.3"
  ["protocols"]=>
  array(9) {
    [0]=>
    string(4) "tftp"
    [1]=>
    string(3) "ftp"
    [2]=>
    string(6) "telnet"
    [3]=>
    string(4) "dict"
    [4]=>
    string(4) "ldap"
    [5]=>
    string(4) "http"
    [6]=>
    string(4) "file"
    [7]=>
    string(5) "https"
    [8]=>
    string(4) "ftps"
  }
}
Gino Pane
  • 4,740
  • 5
  • 31
  • 46
  • is ssl in `curl_version()` anyhow different from `curl -V` ? – Alex Blex May 10 '17 at 17:20
  • That error message rather sounds like it comes from the remote server - which would mean, it is not a firewall issue. Can you check what the value of the PHP ini setting `curl.cainfo` is in each case? – CBroe May 10 '17 at 17:40
  • @AlexBlex, I'm afraid, no. I've added versions to the question. – Gino Pane May 10 '17 at 17:40
  • @CBroe, `curl.cainfo` is empty ("") on server (through `ini_get()`). And I'm afraid I do not know how to get it through console. – Gino Pane May 10 '17 at 17:47
  • Is it empty on the other server, where you said it was working, as well? Can you also compare the phpinfo output regarding cURL with that from your server? – CBroe May 10 '17 at 17:48
  • @CBroe, yes, it's also empty there. I've added server's `curl_version()` to the question. – Gino Pane May 10 '17 at 18:01
  • I suppose the remote address is not under your control? Can you make a request both ways (PHP/cURL command line) to a script of our own, and log all request headers, and see if those differ? – CBroe May 10 '17 at 18:10
  • @CBroe, the only difference, that request from command line has additional user-agent header: `["User-Agent"]=>string(11) "curl/7.47.0"` – Gino Pane May 10 '17 at 18:25
  • Try and add that to the CURLOPT_HTTPHEADER array - any difference? (Might just be that the remote side does some basic "bot" filtering, and simply rejects requests without a User-Agent header set.) – CBroe May 10 '17 at 18:59
  • Well, I see all 3 ssl libraries are different: local php uses OpenSSL/1.0.2g, local cli - GnuTLS/3.4.10, and server php is ancient OpenSSL/0.9.8b. I assume the later one is the one that cause problems. See http://stackoverflow.com/questions/3757071/php-debugging-curl how to debug it. You may want to compare it to the output of cli `curl -vvv` – Alex Blex May 10 '17 at 21:58
  • @AlexBlex, thanks! It helped me to find the reason. – Gino Pane May 11 '17 at 06:48

2 Answers2

1

Thanks to Alex Blex's comment I enabled the verbose output for PHP cURL, and also run command line cURL with -vvv option.

It made me see, that command line request was sent through the proxy, actually, whilst PHP cURL tried to make a direct call, which failed.

Then I used CURLOPT_PROXY option for my PHP request and it also started to work.

Community
  • 1
  • 1
Gino Pane
  • 4,740
  • 5
  • 31
  • 46
  • I've got exact same scenario with docker. Please which `CURLOPT_PROXY` option? – Dominic Pixie Jun 20 '20 at 23:31
  • It depends on your request config. For me it was proxy setting which was different – Gino Pane Jun 21 '20 at 15:52
  • Sorry misread your answer. I though you meant it was one of the php 7 CURLOPT_PROXY_xxxx options eg CURLOPT_PROXY_SERVICE_NAME for example. I see now that is an option itself https://curl.haxx.se/libcurl/c/CURLOPT_PROXY.html – Dominic Pixie Jun 21 '20 at 20:21
0

You neglected to provide the port...

Check your corrected code below:

curl_setopt_array($curl, array(
    CURLOPT_URL => "https://<url_here>",
    CURLOPT_PORT => "443", //MY CORRECTION TO YOUR CODE
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_SSL_VERIFYPEER => false,
    CURLOPT_SSL_VERIFYHOST => false,
    CURLOPT_POST => 1,
    CURLOPT_POSTFIELDS => "<body here>",
    CURLOPT_HTTPHEADER => array(
        "content-type: application/xml"
    ),
));

(see this post also...)

Community
  • 1
  • 1
Theo Orphanos
  • 1,417
  • 1
  • 19
  • 27
  • When the protocol is https, I think cURL is smart enough to figure out the default port on its own. Plus, the error message says that port 443 was used, so I doubt this is the solution. – CBroe May 10 '17 at 17:28
  • Guess you are right... Another thing is: is your server by any chance running SELinux? If yes, disable it and try again... – Theo Orphanos May 10 '17 at 17:39
  • Unfortutately, it does not help. It's a linux docker image. – Gino Pane May 10 '17 at 17:53