Unable to establish SSL connection on first attempt only - php

I have an ecommerce website that has been running for several months with no code changes (and for several years with only minimal changes to the card processing path). I now have a problem where when first opening a connection to the credit card processor secure server, the connection fails. On a second (or third, or fourth, etc.) attempt the connection succeeds. After some length of time--perhaps 5 minutes--the initial connection will fail again and subsequent connections will succeed.
Sample code that comes from the credit card processor's PHP API file:
$url = 'https://esplus.moneris.com:443/gateway_us/servlet/MpgRequestArray';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt ($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS,$dataToSend);
curl_setopt($ch,CURLOPT_TIMEOUT,$gArray[CLIENT_TIMEOUT]);
curl_setopt($ch,CURLOPT_USERAGENT,$gArray[API_VERSION]);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, TRUE);
$response=curl_exec ($ch);
if(!$response) {
print curl_error($ch);
print "\n";
print curl_errno($ch);
print "\n";
} else {
print "Success\n";
}
Output:
% php tester_curl.php
error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol
35
% php tester_curl.php
Success
% php tester_curl.php
Success
% php tester_curl.php
Success
There are some similar questions, but I haven't been able to resolve the problem and I do not see any with the same error message and symptom of subsequent connection attempts succeeding after an initial fail, e.g.:
Unable to establish SSL connection, how do I fix my SSL cert?
curl errno 35 (Unknown SSL protocol error in connection to [secure site]:443) (same error message)
How to fix cURL SSL connection timeout that only happens the first time the script is called (different error msg, but SSL connections fails first attempt, subsequently succeeds)

The server is kind of broken. It does support TLS1.2 and TLS1.0, but not TLS1.1 (replies with TLS1.0 which is ok). This is usually not a problem unless you have client code which tries to enforce specific protocols by excluding others.
The behavior you describe looks like a client which downgrades the connection on failed connection, keeps this downgrade cached for a while but retries with the originally failed version again after some time. To trace the problem down:
check if the problem is also with other servers
check if other clients have the problem with the same server
check the underlying implementation. Curl can use GnuTLS, NSS, OpenSSL and maybe more. From the error message it looks like OpenSSL, but which version?
check for any middlebox (firewall, load balancer...) in the path to the server which might cause problems
do a packet capture and post it here in a form usable with wireshark (e.g. cloudshark)
For more information on how to debug this kind of problems and which additional information would be useful check http://noxxi.de/howto/ssl-debugging.html#aid_external_debugging

I had the exact thing happen with a client using an old VirtualMerchant gateway. It started failing at 5:00 PM on a Monday and magically started working again at 10 AM the next day.
Whether on the command line via openssl, or curl, or through curl in PHP the connection would fail the first time and then if you ran the same command a second latter it would work.
I tried forcing IPv4 (instead of IPv6), setting timeouts, forcing different protocols, downgrading openssl, etc, and none of it work.
The assumption is that this was something DNS and/or server related on the gateway side because nothing we did fixed it and it fixed itself.
We were running an older openssl that only supported up to TLS 1.1, but it was working and then it started working again, so it wasn't only our client. Though, the age of our client must have been part of the issue because other newer clients didn't experience the "first attempt failure" during the same window of time.
Long story short, if this happens it's probably not YOU (besides you have an older OpenSSL) and the other gateway/server you're calling likely will possibly need to fix/tweak something for it to start working again.
Keep in mind, openssl is part of the Linux core packages, so you can't simply upgrade openssl without serious risk of messing up your server. You'll have to upgrade to a newer version of the operating system to get a more modern openssl.

Related

curl doesn't get site contents on PHP via HTTPS

I have read all the internet and tried almost all solutions, nothing works.
If I run curl http://... site, it works but if i run https://... it doesn't.
I' running centos 7 with php 5.6
Nothing happens also if I try the famous answer with
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
The only thing that can help me getting the site is
curl -4svo/dev/null --ciphers ecdhe_ecdsa_aes_128_sha https://.....
however since i need to send my headers, it is not a solution, i need something compatible with the curl_setopt.
UPDATE ERROR
I get this: curl: (35) Cannot communicate securely with peer: no
common encryption algorithm(s).
i think , this problem is caused by the version of cURL not supporting ECC 256 bit SSL certificates and the ECDSA signature algorithm (which is used by CloudFlare). You can test to see if your version of cURL supports this encryption by running:
curl -1IsS --ciphers ecdhe_ecdsa_aes_128_sha https://sslspdy.com
If you get the following, then your cURL is out of date:
curl: (59) Unknown cipher in list: ecdhe_ecdsa_aes_128_sha
This is the magic line!
curl_setopt($ch, CURLOPT_SSL_CIPHER_LIST, 'ecdhe_ecdsa_aes_128_sha');

Connecting to https host with soapclient: how to fix SSL problems? [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 6 years ago.
Improve this question
TLDR
I can't seem to connect to a https endpoint with a SoapClient. As my wget returns a handshake failure, I suspect that is the cause.
How can I do a SOAP request to this server with PHP?
complete
I'm trying to connect to a SOAP server (https). It doesn't have client certificate authentication, so the connection should be pretty straightforward, but sadly it isn't.
The problem is that I keep getting Could not connect to host messages.
The connection method I'm using is working for another server and I've verified that I'm setting the location for this server correctly (changed it to a server I control, and I'm getting response there). I suspect the problem is with the https/ssl connection to the server.
Situation
I'm creating a PHP Soapclient based on a wsdl I have locally.
If I change the endpoint I get Request and Response headers, and everything works as expected.
the machine is reachable from my server, though there is a problem visible when I use wget to connect to it (see below)
Unable to establish SSL connection.
The problem is also visible with openssl connections (see below)
What I tried.
There are a lot of topics about "no connection!", but there is obviously a lot of "my router was bad, I made a typo in the address etc" going on. I did try these settings that were suggested multiple times, but more as a "cut'n'paste" solution to be sure It didn't work" then out of real reasoning. Some comments from me added
Creating a stream_context for the wsdl options. I have tried
$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;
(first only the ssl options with verify_peer and allow_self_signed. Then I added the https array, then finally I added the ciphers key to ssl.)
I found a reference to this bug, but 1) I'm not getting that warning, 2) it seems to be proxy-related and 3) My version shouldn't have the bug anymore. I'm running php 5.3.10
When I try to wget the url, I get:
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
If I try to connect with openssl, I get this:
$ 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:
but if I force ssl3, I get an expected result
$ 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. **
I have tried to add the curl-wrapper from this question with ssl_version set to 3 (as this seems to work on the openssl command above). That wrapper does discard some of the parameters, so I'm not sure how complete this would be. Further, I still get a handshake error, unless I explicitly set checking to false. If I do that (see below), I get an empty response.
curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, false);
Causes
As said above, I suspect the ssl handshake, but I have no clue how to fix it. I don't suspect issues with the wsdl or the client-creation, as the connection does work with another wsdl, the same wsdl with a different location set etc. It is purely this (https) endpoint that's giving me headaches.
Extra tests.
Just as the test above with the curl wrapper I tried sending a minimal soap envelope as #halfwarr seemed to suggest in the comments. Als returns an empty response.
So with above it seems that I do have a method to squeeze an http 204 out of the server, but that's hardly success. But it could be a second problem? Not sure.
I am supposing that I need to try and force the ssl3, but I have no idea how (and this could be the wrong path as well so I'm trying to not have an XY problem here :)
Interesting. Try adding this:
wget https://[[SERVER]]/soap/ —post-file=request.xml —header=”Content-Type: text/xml” -O response.xml
This will save the result as a file named response.xml.
The latest version PHP 5.5.3 will allow you to set the SSL Version. I've seen others that have been able to use a stream_context but, I was unable to get that work as well.
As a work around and fail safe, I used a catch to grab the soap envelope request (similar to what you tested above):
$xml = $client->__getLastRequest()
and send via curl:
curl_setopt($ch, CURLOPT_SSLVERSION, 3);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
That's allowing me to at least move forward.
Have you enabled php_openssl.dll in your php.ini?
Reference:
PHP SOAP cannot connect to an SSL WSDL source

How to resolve cURL Error (7): couldn't connect to host?

I send an item code to a web service in xml format using cUrl(php). I get the correct response in localhost, but when do it server it shows
cURL Error (7): couldn't connect to host
And here's my code:
function xml_post($post_xml, $url)
{
$user_agent = $_SERVER['HTTP_USER_AGENT'];
$ch = curl_init(); // initialize curl handle
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_FAILONERROR, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_TIMEOUT, 50);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_xml);
curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
// curl_setopt($ch, CURLOPT_PORT, $port);
$data = curl_exec($ch);
$curl_errno = curl_errno($ch);
$curl_error = curl_error($ch);
if ($curl_errno > 0) {
echo "cURL Error ($curl_errno): $curl_error\n";
} else {
echo "Data received\n";
}
curl_close($ch);
echo $data;
}
I send the item code to the tally and fetch the details from it. I tried using both the versions php 4+ and php5+, nothing works out Any solution.
CURL error code 7 (CURLE_COULDNT_CONNECT)
is very explicit ... it means Failed to connect() to host or proxy.
The following code would work on any system:
$ch = curl_init("http://google.com"); // initialize curl handle
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
$data = curl_exec($ch);
print($data);
If you can not see google page then .. your URL is wrong or you have some firewall or restriction issue.
“CURL ERROR 7 Failed to connect to Permission denied” error is caused, when for any reason curl request is blocked by some firewall or similar thing.
you will face this issue when ever the curl request is not with standard ports.
for example if you do curl to some URL which is on port 1234, you will face this issue where as URL with port 80 will give you results easily.
Most commonly this error has been seen on CentOS and any other OS with ‘SElinux’.
you need to either disable or change ’SElinux’ to permissive
have a look on this one
http://www.akashif.co.uk/php/curl-error-7-failed-to-connect-to-permission-denied
Hope this helps
If you have tried all the ways and failed, try this one command:
setsebool -P httpd_can_network_connect on
In PHP, If your network under proxy. You should set the proxy URL and port
curl_setopt($ch, CURLOPT_PROXY, "http://url.com"); //your proxy url
curl_setopt($ch, CURLOPT_PROXYPORT, "80"); // your proxy port number
This is solves my problem
In my case I had something like cURL Error (7): ... Operation Timed Out. I'm using the network connection of the company I'm working for. I needed to create some environment variables. The next worked for me:
In Linux terminal:
$ export https_proxy=yourProxy:80
$ export http_proxy=yourProxy:80
In windows I created (the same) environment variables in the windows way.
I hope it helps!
Regards!
Are you able to hit that URL by browser or by PHP script? The error shown is that you could not connect. So first confirm that the URL is accessible.
Check if port 80 and 443 are blocked. or enter - IP graph.facebook.com and enter it in etc/hosts file
you can also get this if you are trying to hit the same URL with multiple HTTP request at the same time.Many curl requests wont be able to connect and so return with error
This issue can also be caused by making curl calls to https when it is not configured on the remote device. Calling over http can resolve this problem in these situations, at least until you configure ssl on the remote.
In my case, the problem was caused by the hosting provider I was using blocking http packets addressed to their IP block that originated from within their IP block. Un-frickin-believable!!!
For a couple of days I was totally blocked on this. I'm very very new to networking/vms but was keen to try set it up myself instead of paying a hosting company to do it for me.
Context
I'm rebuilding the server side for an app that uses php routines to return various bits of data from internal sources as well as external APIs for a map based app. I have started an Oracle VM instance and have installed/set up Apache and php. All running totally fine, until one of my php routines tries to execute a cURL. I start implementing error logging to find that I don't even get a message - just '7', despite implementation being very similar to the above. My php routine accessing an internal file for data was running successfully so I was fairly sure it wasn't an Apache or php issue. I also checked my Apache error logs, nothing telling.
Solution
I nearly gave up - there's talk on disabling SELinux above and in other articles, I tried that and it did work for my purposes, but here's a really good article on why you shouldn't disable SELinux https://www.electronicdesign.com/technologies/embedded-revolution/article/21807408/dont-do-it-disabling-selinux
If temporarily disabling it works and like me you don't want to do this (but it confirms that SELinux is blocking you!), I found a neat little command that actually prints out any SELinux issues in a more readable fashion:
sealert -a /var/log/audit/audit.log
This returned the following:
found 1 alerts in /var/log/audit/audit.log
--------------------------------------------------------------------------------
SELinux is preventing php-fpm from name_connect access on the tcp_socket port 443.
Great, I now get a bit more information than just '7'. Reading further down, I can see it actually makes suggestions:
***** Plugin catchall_boolean (24.7 confidence) suggests ******************
If you want to allow httpd to can network connect
Then you must tell SELinux about this by enabling the 'httpd_can_network_connect' boolean.
Do
setsebool -P httpd_can_network_connect 1
This has been mentioned further above but now I have a bit more context and an explanation as to what it does. I run the command, and I'm in business. Furthermore, my SELinux is still set to enforcing, meaning my machine is more secure.
There are many other suggestions logged out, if you're blocked it might be worth logging out/checking out /var/log/audit/audit.log.

curl_exec($ch) not executing on external domains anymore, why?

I was using cURL to scrape content from a site and just recently my page stated hanging when it reached curl_exec($ch). After some tests I noticed that it could load any other page from my own domain but when attempting to load from anything external I'll get a connect() timeout! error.
Here's a simplified version of what I was using:
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,'http://www.google.com');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 0);
$contents = curl_exec ($ch);
curl_close ($ch);
echo $contents;
?>
Here's some info I have about my host from my phpinfo():
PHP Version 5.3.1
cURL support enabled
cURL Information 7.19.7
Host i686-pc-linux-gnu
I don't have access to SSH or modifying the php.ini file (however I can read it). But is there a way to tell if something was recently set to block cURL access to external domains? Or is there something else I might have missed?
Thanks,
Dave
I'm not aware about any setting like that, it would not make much sense.
As you said you are on a remote webserver without console access I guess that your activity has been detected by the host or more likely it caused issues and so they firewalled you.
A silent iptables DROP would cause this.
When scraping google you need to use proxies for more than a few hand full of requests and you should never abuse your webservers primary IP if it's not your own. That's likely a breach of their TOS and could even result in legal action if they get banned from Google (which can happen).
Take a look at Google rank checker that's a PHP script that does exactly what you want using CURL and proper IP management.
I can't think of anything that's causing a timeout than a firewall on your side.
I'm not sure why you're getting a connect() timeout! error, but the following line:
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 0);
If it's not set to 1, it will not return any of the page's content back into your $contents.

406 "Not Acceptable" error when using JanRain OpenID Library with Google

I am using the latest Janrain openid library example and the discovery process seems to work well with Yahoo, myopenid.com and others...
But I am stuck with Google endpoint (https semicolon //www.google.com/accounts/o8/id). Consumer.php just returns a 406 apache error, before I am redirected to google's page.
All my installation is available here :
http://www.coplango.com/vendor/openid/examples/
Click on consumer to try the consumer example, but discovery.php fails the same way,proving it happens during discovery...
You can also check detect.php to check my installation - The HTTP fetching test fails with a 503 because it tries to reach an address which returns a 503. Rest is fine.
I supposed it was down to php-yadis specifying Accept: application/xrds+xml header but I checked the code and other types are also accepted such text/html and application/xhtml+xml.
Anyone came accross this?
Any clue?
Thank you very much!
Ok,
I have investigated further and it seems to be down to my provider, who returns a 406 error if any string containing the death word "/id" is passed as GET parameter. Took me days to figure out it was not down to openid !!
For info I am using PlanetHoster, if anyone else ever comes accross this. I have sent them a ticket request and waiting for their answer.
running the consumer example at my machine, i get the following error:
Got no response code when fetching https://www.google.com/accounts/o8/id
CURL error (60): SSL certificate problem, verify that the CA cert is OK. Details:
error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
this means curl fails verifying google's https server certificate. you can workaround this by either providing curl with CA certificates to verify google's certificate via CURLOPT_CAINFO/CURLOPT_CAPATH, or - easier - stop validating the cert via CURLOPT_SSL_VERIFYPEER. the following change in Auth/Yadis/ParanoidHTTPFetcher.php accomplishes latter for me:
--- ParanoidHTTPFetcher.php.orig 2009-04-22 02:31:20.000000000 +0800
+++ ParanoidHTTPFetcher.php 2009-09-30 22:35:24.093750000 +0800
## -127,6 +127,9 ##
Auth_OpenID_USER_AGENT.' '.$curl_user_agent);
curl_setopt($c, CURLOPT_TIMEOUT, $off);
curl_setopt($c, CURLOPT_URL, $url);
+
+ // don't verify server cert
+ curl_setopt($c, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_exec($c);
of course, your curl installation must also support ssl - check your phpinfo(). also, if CURLOPT_SSL_VERIFYPEER is disabled, CURLOPT_SSL_VERIFYHOST may also need to be TRUE or FALSE.
see also http://www.openrest.eu/docs/openid-not-completely-enabled-for-google.php (via the Related Why doesn't Google OpenID provider work with PHP-OpenId on my server?).
SOLUTION:
In the .htaccess file put
SecFilterEngine Off

Categories