2

I have a bug I am hoping someone can shed some insight on. I am fetching data from a client's API, and it works...90% of the time. About 1/10 times (but random frequency), curl_exec returns false with error:

OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to api.site.com:443

I've checked numerous threads on this error, and in all cases I see the issue is happening 100% of the time for the person. Has anyone dealt with something like this? If it's working sometimes and failing other times, where is the issue likely to be (the site/server or the api)?

I have experimented with different settings and nothing has fixed the issue. I've tried with and without CURLOPT_PINNEDPUBLICKEY, with and without CURLOPT_SSL_VERIFYHOST => 0, CURLOPT_SSL_VERIFYPEER => 0, with and without forcing HTTP and SSL versions. It fails always when I set these incorrectly, so I am pretty sure I have the right versions selected. The code exists in a custom joomla component which has been stable before this API switch. Here is my code:

$headers = array(
    'X-apikey: '.$this->apikey,
    "Cache-Control: no-cache",
);
$url = $this->url;

$curl = curl_init();

curl_setopt_array($curl, array(
    CURLOPT_URL => $url,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_HTTPHEADER => $headers,
    CURLOPT_SSL_VERIFYHOST => 0,
    CURLOPT_SSL_VERIFYPEER => 0,
    CURLOPT_SSLVERSION => CURL_SSLVERSION_TLSv1_2,
    CURLOPT_PINNEDPUBLICKEY => '/path/to/api.site.com.pubkey.der',
));

$data = curl_exec($curl);
$result = json_decode($data);

curl_close($curl);

PHP version: 7.3.10

curl version: 7.66.0

openSSL library version: OpenSSL 1.1.1d 10 Sep 2019

Output from hanshenrik comment (removed company info):

Error output:

string(385) "* Trying xxx.xxx.xxx.xxx:443... * TCP_NODELAY set * Connected to api.site.com (xxx.xxx.xxx.xxx) port 443 (#0) * ALPN, offering http/1.1 * successfully set certificate verify locations: * CAfile: /usr/local/etc/openssl@1.1/cert.pem CApath: /usr/local/etc/openssl@1.1/certs * OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to api.site.com:443 * Closing connection 0 "

Success Output

string(1324) "* Trying xxx.xxx.xxx.xxx:443... * TCP_NODELAY set * Connected to api.site.com (xxx.xxx.xxx.xxx) port 443 (#0) * ALPN, offering http/1.1 * successfully set certificate verify locations: * CAfile: /usr/local/etc/openssl@1.1/cert.pem CApath: /usr/local/etc/openssl@1.1/certs * SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384 * ALPN, server did not agree to a protocol * Server certificate: * subject: C=US; ST=Illinois; L=Chicago; O=Company Name; CN=*.site.com * start date: May 14 15:20:46 2019 GMT * expire date: Aug 8 15:41:00 2020 GMT * issuer: C=US; ST=Arizona; L=Scottsdale; O=GoDaddy.com, Inc.; OU=http://certs.godaddy.com/repository/; CN=Go Daddy Secure Certificate Authority - G2 * SSL certificate verify ok. > GET /endpoint/id?fields=field1,field2,etc HTTP/1.1 Host: api.site.com Accept: / X-apikey: xxxxx Cache-Control: no-cache * Mark bundle as not supporting multiuse < HTTP/1.1 200 OK < Date: Tue, 08 Oct 2019 21:21:45 GMT < Server: Apache < Content-Length: 614 < Content-Type: application/json < * Connection #0 to host api.site.com left intact "

Ricky Goldman
  • 349
  • 1
  • 7
  • Are you always using the same endpoint? Or is this happening to some endpoints and not others? – RiggsFolly Oct 08 '19 at 13:07
  • I'm using several endpoints from the same API, and it happens to all. The calls to each endpoint are not changing with each page load. I've verified nothing funky is happening before curl (the url and api key remain the same, error or not). – Ricky Goldman Oct 08 '19 at 13:44
  • 1
    replace ```$data = curl_exec($curl);``` with ```$errf=tmpfile();curl_setopt_array($ch,[CURLOPT_VERBOSE=>1,CURLOPT_STDERR=>$errf]);$data = curl_exec($curl);if(curl_errno($curl)){/*https://bugs.php.net/bug.php?id=76268*/rewind($errf);var_dump(stream_get_contents($errf));}``` , log such an error on an endpoint, then log a successfull request on the same endpoint, what do you get in both cases? – hanshenrik Oct 08 '19 at 20:29
  • I've updated the output in the original message. It looks like the success is using TLSv1.2, but the failure is using OpenSSL. My code is the same and adds CURLOPT_SSLVERSION so I'm confused to why this would happen. – Ricky Goldman Oct 08 '19 at 21:27
  • 1
    **[You should not switch off `CURLOPT_SSL_VERIFYHOST` or `CURLOPT_SSL_VERIFYPEER`](https://paragonie.com/blog/2017/10/certainty-automated-cacert-pem-management-for-php-software)**. It could be a security risk! [Here is how to get the certificate bundle if your server is missing one](https://stackoverflow.com/a/32095378/1839439) – Dharman Oct 11 '19 at 18:53

0 Answers0