frankenphp icon indicating copy to clipboard operation
frankenphp copied to clipboard

Unable to connect with STARTTLS: stream_socket_enable_crypto(): SSL operation failed with code 5

Open range-of-motion opened this issue 1 year ago • 13 comments

What happened?

Not sure if this is due to FrankenPHP, but I don't have this issue using PHP-FPM. Whenever I try and send an e-mail using Laravel to Postmark, I get this. I already tried setting MAIL_ENCRYPTION=null, but no luck.

Build Type

Standalone binary

Worker Mode

Yes

Operating System

GNU/Linux

CPU Architecture

x86_64

Relevant log output

[2024-02-17 21:29:14] production.ERROR: Unable to connect with STARTTLS: stream_socket_enable_crypto(): SSL operation failed with code 5. OpenSSL Error messages:
error:80000002:system library::No such file or directory
error:80000002:system library::No such file or directory
error:80000002:system library::No such file or directory
error:0A000086:SSL routines::certificate verify failed {"userId":1,"exception":"[object] (Symfony\\Component\\Mailer\\Exception\\TransportException(code: 0): Unable to connect with STARTTLS: stream_socket_enable_crypto(): SSL operation failed with code 5. OpenSSL Error messages:
error:80000002:system library::No such file or directory
error:80000002:system library::No such file or directory
error:80000002:system library::No such file or directory
error:0A000086:SSL routines::certificate verify failed at /var/www/spark-plug/vendor/symfony/mailer/Transport/Smtp/Stream/SocketStream.php:171)

range-of-motion avatar Feb 17 '24 21:02 range-of-motion

Are we missing ca-certificates @dunglas... that's a pretty weird error.

withinboredom avatar Feb 18 '24 18:02 withinboredom

This look like the same problem as https://github.com/beyondcode/expose/issues/391#issuecomment-1866184348 (Herd also uses static-php-cli under the hood as far as I know).

As the standalone binary doesn't bundle certificates, you need to point OpenSSL to your local certificates installation in your php.ini file (you can add one in the root of your app).

This is something that we need to document (help welcome).

dunglas avatar Feb 18 '24 20:02 dunglas

Hi,

I've also run into this issue (building on mac). I've added my own cacert.pem into my embeded project that I then want to add to the php.ini.

I need it working on cli (./frankenphp-mac-arm64 php-cli bin/console test:https-request).

I'm building by cloning the project and running:

EMBED=/my-project ./build-static.sh

Neither when adding a php.ini to the root of the embedded project nor adding the PHP_INI_SCAN_DIR to the build-static command works for me.

Any clue how I can add the cacert.pem path?

SiebeVE avatar Feb 23 '24 13:02 SiebeVE

This likely doesn't work because it's impossible to reference the PEM file because the app is decompressed in a temporary directory with a random name.

Using a script to copy the PEM file in a known path (like /cacert.pem) could work as a workaround, but we need to figure out a better solution.

dunglas avatar Feb 23 '24 15:02 dunglas

Hi, I also encountered the same problem

Are there any guides on how to resolve this issue?

hongfanmeng avatar Mar 11 '24 02:03 hongfanmeng

Here is what I think we should do:

  1. Embed the latest version of the "official" cURL CA bundle when building the binary (allow the user to provide its own)
  2. Extract the embedded bundle as a known path of it doesn't already exists
  3. Change the default php.ini settings for cURL and OpenSSL to reference this bundle

dunglas avatar Mar 27 '24 05:03 dunglas

@dunglas Any chance there's a workaround in the meantime until this is resolved?

LukeAbell avatar Apr 05 '24 23:04 LukeAbell

Copying the CA bundle at a known path and hardcoding this absolute path in php.ini should work.

I'll try to take a look soon.

dunglas avatar Apr 06 '24 07:04 dunglas

In case it helps anyone in the future, this caused me quite some headaches. In the end, I fixed it with these simple changes to my dockerfile:

RUN apk update && apk add --no-cache ca-certificates && rm -rf /var/cache/apk/*

ENV SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt
ENV SSL_CERT_DIR=/etc/ssl/certs

I was very confused why laravel tinker was working to send emails, but the web browser running frank was not. Then I noticed after dumping openssl_get_cert_locations() in both places that the results differed, which is where I saw frank was using the above environment variables.

SimonMacIntyre avatar Jun 25 '24 13:06 SimonMacIntyre

@SimonMacIntyre thanks! Would you mind opening a docs PR about that? I'm sure this will help a lot of people. In this file for instance: https://github.com/dunglas/frankenphp/blob/main/docs/known-issues.md

dunglas avatar Jun 25 '24 14:06 dunglas

I'd be happy to!

SimonMacIntyre avatar Jun 25 '24 14:06 SimonMacIntyre