reactphp / socket

Async, streaming plaintext TCP/IP and secure TLS socket server and client connections for ReactPHP.

Home Page:https://reactphp.org/socket/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

TLS Server fails without explanation

siolfyr opened this issue · comments

Using react/socket version 1.2.0, using php --version 7.0.32-0ubuntu0.16.04.1

Started a server as in the README via:

$server = new React\Socket\Server('tls://0.0.0.0:25', $loop, array(
    'tls' => array(
        'local_cert' => 'secret.pem'
    )
));

And created the self-signed cert using the method in the 99 self-sign example file, which should in theory be valid. Also tried with a LetsEncrypt certificate, and got the same result.

The result is a server which triggers this error when hitting it with openssl s_client -connect site.com:25:
error: Connection from tcp://etc:etc failed during TLS handshake: Unable to complete TLS handshake: Unable to set private key file `/blah/blah/secret.pem'

The file exists and the error isn't the same as an error for a nonexistent file.

The server worked great before attempting to enable TLS.

What could be the issue? Any tips on debugging the issue with the certificate?

That's strange, this shouldn't have happened.

Here's an excerpt from the README on how to diagnose these issues:

Note that the certificate file will not be loaded on instantiation but when an incoming connection initializes its TLS context. This implies that any invalid certificate file paths or contents will only cause an error event at a later time.

Whenever a client fails to perform a successful TLS handshake, it will emit an error event and then close the underlying TCP/IP connection:

$server->on('error', function (Exception $e) {
echo 'Error' . $e->getMessage() . PHP_EOL;
});

Other than that, how was this pem file created? Have you tried verifying this in another program that can load pem files? Have you verified the same error happens with the demo certificate that ships in the examples/ folder?

Hmm, that's odd. I tried the localhost.pem from the examples folder just now and it worked fine.

The cert was generated using the example in the examples folder, like this:
php 99-generate-self-signed.php site.com swordfish > secret.pem

I also tried using a LetsEncrypt cert, which works for my website fine. I also tried using a cert created via this method (option 1):
https://workaround.org/ispmail/jessie/create-certificate

My openssl version is: OpenSSL 1.0.2g 1 Mar 2016

I'll try using the cert I made in Nginx and see if it has a problem with it.

The cert was generated using the example in the examples folder, like this:
php 99-generate-self-signed.php site.com swordfish > secret.pem

This script will encrypt your private key with the given passphrase. This means you have to pass the same passphrase to the server so it can actually read this certificate. Here's an excerpt, again from the README:

If your private key is encrypted with a passphrase, you have to specify it like this:

$server = new React\Socket\Server('tls://127.0.0.1:8000', $loop, array(
    'tls' => array(
        'local_cert' => 'server.pem',
        'passphrase' => 'secret'
    )
));

Oh, damn, I did not read that code carefully enough. I thought swordfish was the name of the encryption algorithm.

Careless mistake on my part. I tested it and it's working fine. Thanks so much for the help!

@siolfyr Heh, no worries, these things happen (it's always the little details..) and I'm sure this ticket is also something more people will stumble over in the future 👍 Either way, I'm happy to hear this is resolved, so welcome to ReactPHP!