amphp / http-client

An advanced async HTTP client library for PHP, enabling efficient, non-blocking, and concurrent requests and responses.
https://amphp.org/http-client
MIT License
706 stars 66 forks source link

TLS negotiation failed when using HttpClientBuilder #298

Closed devupix closed 1 year ago

devupix commented 3 years ago

Hi,

I am using Http Client to fetch data from a server. The code was working fine but suddenly it stopped working and now it throws this error.

Amp\Socket\TlsException: TLS negotiation failed:
stream_socket_enable_crypto(): SSL operation failed with code 1.
OpenSSL Error messages:
error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed

You can find complete details in the file attached below.

error.txt

Here is the code I am using.

$client = HttpClientBuilder::buildDefault(); $request = new Request($url); $request->setTransferTimeout($this->httpClientTimeoutSeconds 1000); $request->setInactivityTimeout($this->httpClientTimeoutSeconds 1000);

try { $promise = $client->request($request);

$response = wait($promise);
$content = wait($response->getBody()->buffer());

} catch (Throwable $e) { throw new Exception("(-‸ლ) Request for URL: " . $url . " failed. " . $e->getMessage()); }

I think it will work if I disable SSL peer verification but I am unable to find the code/example for that.

Any help would be appriciated.

Thanks

kelunik commented 3 years ago

The proper way to fix this error is to install a valid certificate on the server. If you're using an internal CA or self-signed certificate, the better way is to mark these certificates as trusted instead of disabling the peer verification completely.

devupix commented 3 years ago

Hi, thank you for your quick response. It is working perfectly on the production. Recently it started giving this error on the development environment.

I understand that proper way would be installing a valid certificate, but I possess little understanding of server related stuff and it being development environment, it will be okay to disable peer verification. Thoughts?

Thanks

kelunik commented 3 years ago

Do you know what changed in your development environment? Do you know the exact date when the behavior changed? Does visiting the page with the browser work?

devupix commented 3 years ago

I'm not aware of what changed in the development environment. It was working last week and then suddenly stopped working this week. This works from production as well as my local environment though.

The behaviour changed somewhere during the last week.

Visiting the page from browser works perfectly. If I run this code on production environment or my local environment, it works as well, stopped working for development environment.

kelunik commented 3 years ago

If it was September 30th, I would have guess it's the expired Let's Encrypt root certificate.

If it works in the browser without a certificate warning, that's great! Let's work from there to get to the root cause. Which browser do you use? Do you know how to view the certificate chain in the browser? If so, what's the certificate chain, so the non-leaf certificates?

devupix commented 3 years ago

Yes, it can be 30th September when it stopped working.

Firstly thank you for the help you are providing. I appreciate it.

Let me explain the scenario a bit more. I am fetching data from a 3rd party server using the amp/http-client bundle. I have created a command in Symfony which I run from the terminal. In that command I have applied the code I shared above which fetches data from a 3rd party server and save it to the database.

Also, I have the website setup on 3 places.

  1. My local environment, where I do development.
  2. Development environment, where I test changes before making them live.
  3. Production environment, the live website.

Now this works perfectly a few days ago. But recently it stopped working on development server. The 3rd party URL which I request to provide us data also works perfectly when hit in a browser.

I use Chrome as well as Firefox.

devupix commented 3 years ago

If someone can let me know please how can I modify the above code to pass the peer verification for development purposes only that would be very helpful.

cangokdayi commented 2 years ago

For those still looking for a solution: the following example did the job for me, I was suffering from the same issue on my local dev server, and building the client instance like this worked out fine for me. I'm no expert on this library so don't ask me questions that I wouldn't know the answer to.

I'm using amphp/http-client version 4.6

Let's include these classes first (if you haven't already)

use Amp\Http\Client\Connection\DefaultConnectionFactory;
use Amp\Http\Client\Connection\UnlimitedConnectionPool;
use Amp\Socket\ClientTlsContext;
use Amp\Socket\ConnectContext;

And in your function where you create your client instance, create it like this:

$TLS = (new ClientTlsContext(''))
    ->withoutPeerVerification() // I believe this one acts like the SSL_VERIFYPEER option of curl
    ->withSecurityLevel(0); // And this one disables SSL verification completely

$context = (new ConnectContext)
    ->withTlsContext($TLS);

$client = (new HttpClientBuilder)
    ->usingPool(new UnlimitedConnectionPool(new DefaultConnectionFactory(null, $context)))
    ->build();
// while digging thru the code I saw the HttpClientBuilder was using the UnlimitedConnectionPool with DefaultConnectionFactory so that's why I've used them in my code, if your pool config is different then adjust it accordingly

$request = new Request('{YOUR REQUEST}');

If someone can let me know please how can I modify the above code to pass the peer verification for development purposes only that would be very helpful.

Same issue https://github.com/amphp/http-client/issues/174